6
respostas

TenantProducer null

Olá, pessoal! Estou tentando montar um ambiente SaaS com o seguinte cenário:

Java EE + JSF + Wildfly

Classse: MultiTenantConnectionProviderImpl

import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;

public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider, ServiceRegistryAwareService {

    private static final long serialVersionUID = 1L;

    private DataSource dataSource;

    @Override
    public boolean supportsAggressiveRelease() {
        return false;
    }

    @Override
    public void injectServices(ServiceRegistryImplementor serviceRegistry) {
        try {
            final Context init = new InitialContext();
            dataSource = (DataSource) init.lookup("java:jboss/datasources/AplicacaoDS");
        } catch (final NamingException e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("rawtypes")
    @Override
    public boolean isUnwrappableAs(Class clazz) {
        return false;
    }

    @Override
    public <T> T unwrap(Class<T> clazz) {
        return null;
    }

    @Override
    public Connection getAnyConnection() throws SQLException {
        final Connection connection = dataSource.getConnection();
        return connection;
    }

    @Override
    public Connection getConnection(String tenantIdentifier) throws SQLException {
        final Connection connection = getAnyConnection();
        try {
            connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");
        } catch (final SQLException e) {
            throw new HibernateException("Error trying to alter schema [" + tenantIdentifier + "]", e);
        }
        return connection;
    }

    @Override
    public void releaseAnyConnection(Connection connection) throws SQLException {
        try {
            connection.createStatement().execute("SET SCHEMA 'public'");
        } catch (final SQLException e) {
            throw new HibernateException("Error trying to alter schema [public]", e);
        }
        connection.close();
    }

    @Override
    public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
        releaseAnyConnection(connection);
    }

}

Classe: CurrentTenantIdentifierResolverImpl

import javax.inject.Inject;

import org.hibernate.context.spi.CurrentTenantIdentifierResolver;

public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {

    @Inject
    @TenantInject
    private Tenant tenant;

    @Override
    public String resolveCurrentTenantIdentifier() {
        return tenant.getNome();
    }

    @Override
    public boolean validateExistingCurrentSessions() {
        return true;
    }

}

Classe: Tenant

import java.io.Serializable;

public class Tenant implements Serializable {

    private static final long serialVersionUID = 1L;

    private String nome;

    public Tenant() {
    }

    public Tenant(String nome) {
        super();
        this.nome = nome;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((nome == null) ? 0 : nome.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Tenant other = (Tenant) obj;
        if (nome == null) {
            if (other.nome != null)
                return false;
        } else if (!nome.equals(other.nome))
            return false;
        return true;
    }

}

@interface

import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, CONSTRUCTOR})
public @interface TenantInject {
}

Classe: TenantProducer

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.faces.context.FacesContext;

@RequestScoped
public class TenantProducer {

    @Produces
    @RequestScoped
    @TenantInject
    public Tenant create() {
        Tenant tenant = (Tenant) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("tenant");
        return tenant;
    }

}

Porém, na classse CurrentTenantIdentifierResolverImpl eu não consigo injetar o meu Tenant. Alguém sabe dizer pq?

6 respostas

Oi Phillip, tudo bem ?

Bem legal esse seu projeto cara :D

Imagino que você não consegue fazer isso devido a classe não estar sendo gerenciada pelo servidor, talvez fazer ela ser um componente deva ajudar.

Olá, Matheus!

Como eu faria para essa classe ser gerenciada pelo servidor?

Provavelmente você tá usando o cdi, tenta usar o @Named

Olá, Matheus!

Mesmo com a anotação @Named o Tenant não é injetado.

@Named
public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver, Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    @TenantInject
    private Tenant tenant;

    @Override
    public String resolveCurrentTenantIdentifier() {
        System.out.println(">>> Tenant is null " + (tenant == null));
        return "agencia_teste";
    }

    @Override
    public boolean validateExistingCurrentSessions() {
        return false;
    }

}

Fala Philip, blz?

Vc tem algum outro Produtor da classe Tenant? Porque vc está o usando um Qualifier para ele, acredito que vc não precisaria da Anotação TenantInject.

Outra coisa, como o CDI que vai instanciar essa classe através da injeção o construtor com parametros da classe Tenant tb deve ser anotado com @Inject (apenas o construtor).

Fala Philip, blz?

Vc tem algum outro Produtor da classe Tenant? Porque vc está o usando um Qualifier para ele, acredito que vc não precisaria da Anotação TenantInject.

Outra coisa, como o CDI que vai instanciar essa classe através da injeção o construtor com parametros da classe Tenant tb deve ser anotado com @Inject (apenas o construtor).