0

Im setting new database connection with Sql Server using EntityManager(already got EM for mySql database). But during start up app does not distinguish EntityManagers due to some problem with my qualifiers. Can someone tell how to make my EM's distinguishable?

I have added necessary configuration in persistence.xml file. What i have tried so far:

  1. Created Qualifiers for both mySql and SqlServer units.
    • annotated injected fields, constructors, produces methods etc
    • even tried to create two different classes for EntityManagerProducer and annotated only them, but it is still not working.
    • annotated injected EM in abstract class, which all my DAO's use(got two different abstract classes for each EntityManager Injection).
  2. Listed all loaded beans - as a result i can see that my Qualifiers are not taken into account Qualifiers:[javax.enterprise.inject.Default,javax.enterprise.inject.Any,javax.inject.Named], EntityManagerProducer...

I got fallowing classes: EntityManagerFactoryProducer and EntityManagerProducer.

@ApplicationScoped
public class EntityManagerFactoryProducer {
    private static EntityManagerFactory mySqlEMFactory;
    private static EntityManagerFactory sqlServerEMFactory;

    public static EntityManagerFactory getEMFactoryMySql() {
        if (mySqlEMFactory != null)
            return mySqlEMFactory;
        return createEMFactoryMySql();
    }

    public static EntityManagerFactory getEMFactorySqlServer() {
        if (sqlServerEMFactory != null)
            return sqlServerEMFactory;
        return createEMFactorySqlServer();
    }

    private static synchronized EntityManagerFactory createEMFactoryMySql() {
        // To avoid race conditions
        if (mySqlEMFactory != null)
            return mySqlEMFactory;
        String unitName = "mysql";
        mySqlEMFactory = Persistence.createEntityManagerFactory(unitName);
        return mySqlEMFactory;
    }

    private static synchronized EntityManagerFactory createEMFactorySqlServer() {
        // To avoid race conditions
        if (sqlServerEMFactory != null)
            return sqlServerEMFactory;
        String unitName = "sqlServer";
        sqlServerEMFactory = Persistence.createEntityManagerFactory(unitName);
        return sqlServerEMFactory;
    }

    @Produces
    @MySql
    @ApplicationScoped
    public EntityManagerFactory createEntityManagerFactoryMySql() {
        return getEMFactoryMySql();
    }

    @Produces
    @SqlServer
    @ApplicationScoped
    public EntityManagerFactory createEntityManagerFactorySqlServer() {
        return getEMFactorySqlServer();
    }

    public void dispose(@Disposes EntityManagerFactory emFactory) {
        if (emFactory.isOpen())
            emFactory.close();
    }
}

public class EntityManagerProducer {
    @Inject
    @MySql
    private EntityManagerFactory mySqlemFactory;

    @Inject
    @SqlServer
    private EntityManagerFactory sqlServerFactory;

    protected EntityManagerProducer() {
    }

    public EntityManagerProducer(EntityManagerFactory mySqlemFactory, EntityManagerFactory sqlServerFactory) {
        this.mySqlemFactory = mySqlemFactory;
        this.sqlServerFactory = sqlServerFactory;
    }

    @Produces
    @MySql
    @RequestScoped
    public EntityManager createEntityManagerForMySql() {
        return mySqlemFactory.createEntityManager();
    }

    @Produces
    @SqlServer
    @RequestScoped
    public EntityManager createEntityManagerForSqlServer() {
        return sqlServerFactory.createEntityManager();
    }

    public void close(@Disposes EntityManager em) {
        if (em.isOpen())
            em.close();
    }
}
        //second looks the same
        Qualifier
        @Retention(RetentionPolicy.RUNTIME)
        @Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE})
        public @interface MySql {
        }

 // And then usage of EM in abstract class for all mySql DAO's
   //Sql Server EM is injected the same way in his abstract class for DAO's
    public abstract class AbstractBaseReadDao <T extends BaseEntity> {
      @Inject @MySql private EntityManager em;
      protected AbstractBaseReadDao() {}
      protected AbstractBaseReadDao( EntityManager em ) { this.em = em; }
      //...
    }

After many tries Im always getting the same error

"AM org.apache.webbeans.component.AbstractInjectionTargetBean postConstructDefault SEVERE: An error occurred while executing [@PostConstruct.] javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: Invalid object name 'person'. ... Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'person'"

On the startup im calling service which authorize user using MySql database -table PERSON. So im getting this error because EM with Sql Server configuration is trying to select person from table PERSON(there is no table PERSON in Sql Server database) and it should use EM for MySql. And second think is, that according to where i put annotation, app sometimes is not event creating EM instance for Sql Server.

Antyfan
  • 35
  • 2
  • 5
  • Please would you post the correct the code. That can't be working, there are ambiguities. And did you know, that you can Annotate the EntityManager directly with @PersistenceContext("unitname") you don't need to use Factories. – aschoerk Jul 29 '19 at 21:47
  • @aschoerk sorry for my mistake. I edited code, so you can now copy and paste it and everythink should be ok. I know that i could use @PersistenceContext("unitname"), but my requirement is to use it just like i posted it. – Antyfan Jul 30 '19 at 05:39
  • Why are the two Producers in EntityManagerproducer not qualified. That should generate Ambiguities. And what do you need the Constructor with those two Factories for? The Factories should get injected directly. The default constructor is private, so, how will this work? – aschoerk Jul 30 '19 at 06:13
  • @aschoerk i edited code once again, by adding Qulifiers in EntityManagerProducer class in Produces method but like i said. I just posted one of the i belive 20 version of my code. In description i wrote that i have tried put annotation with Qualifiers everywhere - all possible options but it doesn't matter where i put them it is just not working. The constructor with Factory arguments is there because of project convention, but i have tried just now to remove both constructors or leaving only no args constructor - it did not make any difference. – Antyfan Jul 30 '19 at 06:52
  • Sorry, I can't help you. The constructor is used doing new in your code? Then those injects will not work. @RequestScoped is not necessary with EntityManagers, since they are threadlocal. The Qualifiers now look ok, but the producing can't work, since Weld does not know about the bean which should produce, since you did new on it. That is all very strange. Please check with CDI-Docu, Project-Architect, – aschoerk Jul 30 '19 at 07:25

0 Answers0