Spring Boot: Why isn't entity being scanned in createQuery when using multiple datasources? - spring-boot

I am using Spring Boot 2.3.0. I have 2 data sources one for oracle and one for h2 defined in application.properties.
I have to 2 #Configuration classes for the data configurations. Both classes implement:
DataSource
PlatformTransactionManager
LocalContainerEntityManagerFactoryBean
In LocalContainerEntityManagerFactoryBean I set up:
setDataSource
setPackagesToScan
setJpaVendorAdapter
The application starts up properly, I can even do .findAll on the table in the H2 database, however
as soon as I start executing custom methods in the repository implementation, such as this:
#Transactional(readOnly = true)
private Optional<List<Foo>> findFooByState(Optional<Integer> id, Foo.State state) {
CriteriaBuilder cp = em.getCriteriaBuilder();
CriteriaQuery<Foo> cqFoo= cp.createQuery(Foo.class);
Root<Foo> fooRoot = cqFoo.from(Foo.class);
[...]
Spring throws an exception such as:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
[Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Not an entity: class foo.Foo;
nested exception is java.lang.IllegalArgumentException: Not an entity: class foo.Foo] with root cause
Package foo is added in setPackagesToScan as I wrote earlier.
I have tried various things with #Transactional, e.g. remove it, add the name of the transaction manager specified in the DataSource in it, move the #Transactional to the #GetMapping, but none of it helped.
Does anybody have any clue what am I doing wrong?
Thanks,

I had a similar problem. Most probably you haven`t configured JPA repositories base packages to pick up different entities for different data sources. You can have a look at my guide on how to configure two data sources
in Spring Boot application. Hope it will help!

Ok, I was lame. I had to:
setPersistenceUnitName in the LocalContainerEntityManagerFactoryBean instantiation method
I had to use the proper #PersistenceContext with the proper unitName

Related

In the Spring boot, when I fetch data from DB, error popping List is null, but data available in db table

data not fetching, error thrown list is empty but data available in DB
service class code,
Service class code block
Controller class
Controller code block
error msg
Error msg
You must add #Autowired to have a dependency injected:
#Autowired
private country gocount;
Bean wiring is missing here hence null pointer exception is being thrown.
You need to do one of the following.
Autowire the dependency
#Autowired
private Country repocount;
Make a constructor and set this dependency.
Using a Lombok annotation may also help.
By seeing the error it is cleared that You haven't Autowired the Bean In controller this will surely solve the problem

Injecting an entitymanager in #ApplicationScoped bean

I am porting an existing JBOSS JEE application to Quarkus. I am using a number of HV custom validators that require injection.
For that purpose I've defined all custom validators that require injection as bean in my libraries like this:
#ApplicationScoped
public class SomeValidator implements ConstraintValidator<SomeValidation, AnObject> {
#Inject
public BeanUsingEntityManager bean;
Note: It is common code, so it should remain working on JBOSS as well
Next I defined a REST service. The REST service makes use of an application scoped bean like this.
#ApplicationScoped
public class ApplicationContext {
#PersistenceContext( unitName = "A" )
EntityManager em;
#Produces
#EnityManagerA // required qualifier to make datasource unique in JEE context (there are more)
public EntityManager produce() {
return em;
}
// NOTE: quarkus does not allow the #Produces on a field, which is allowed in JBOSS hence the method
#Produces
public BeanUsingEntityManager createBeanUsingEntityManager () {
// some logic that requires the entity manager.
}
}
Now the problem is simplified, but I keep on running into an error message.
Caused by: javax.enterprise.inject.CreationException: Synthetic bean instance for javax.persistence.EntityManager not initialized yet: javax_persistence_EntityManager_b60c51739990fc921960fc78caeb075a811a91a6
- a synthetic bean initialized during RUNTIME_INIT must not be accessed during STATIC_INIT
- RUNTIME_INIT build steps that require access to synthetic beans initialized during RUNTIME_INIT should consume the SyntheticBeansRuntimeInitBuildItem
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.create(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:167)
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.create(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:190)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext.access$000(AbstractSharedContext.java:14)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.get(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:222)
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.get(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:238)
at nl.bro.gm.gmw.dispatch.resources.ApplicationContext_Bean.create(ApplicationContext_Bean.zig:131)
... 59 more
I'm new to Quarkus. So, not sure to how to handle this issue or even if I make the correct assumptions. I can imagine that Quarkus wants to give me a fresh entitymanager each request (which I understand), but that poses a problem for my application scoped beans.
What am I doing wrong here?
So, the full answer is that the EntityManager is created at the runtime init phase whereas the ValidatorFactory (and the ConstraintValidators) are created at static init time.
The Quarkus bootstrap goes static init -> runtime init.
So in your case, you can't access a #Singleton bean which uses the EntityManager during static init as it's not yet available.
Making your bean #ApplicationScoped will create a proxy and avoid this chicken and egg problem.
You will have only one BeanUsingEntityManager for your whole application.
The EntityManager is a bit different because we wrap it and you will get one new EntityManager/Session per transaction, which is what is expected as EntityManagers/Sessions are not thread safe.

spring autowired aop circular dependency

I'm using java config with #ComponentScanin order to initialize my beans
and #EnableAspectJAutoProxy(proxyTargetClass=true)to use cglib proxies.
In this project we have a lots of generated services autowired between them using #Autowired. It works pretty well.
But, for some of these services I've added #Async (I've also added #EnableAsync(proxyTargetClass = true)on my #Configurationclass).
After that, I'm getting:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ConversationUserLocalService': Bean with name 'ConversationUserLocalService' has been injected into other beans [ConversationUserHistoryLocalService] i
n its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'a
llowEagerInit' flag turned off, for example.
I guess this is because Spring is injecting the service with #Asyncmethod BEFORE AOP creates the proxy.
Could this be the problem?
How I should fix it?
In order to try to clarify my problem, let's say I have:
#Service A, B & C;
A has autowired B & C, B has autowired A & C, C has autowired A & B;
C has a method marked as #Async.
When Spring initialize applicationContext, it tries to initialize A, but needs B & C, so it initializes them. But after all, AOP tries to make a proxy of C (because #Async) and then it detects that autowired C into B and A is not the same as proxy of C so it fails.
I hope this can explain a little more what is happening.
Finally I sorted it out using #Lazyon services (with methods annotated with #Async), and also, where they were autowired.
This way I guess Spring only initialize and autowires those services when they're required instead of on application context initialization.
I have same issue and I solved this issue:
I identified which #Autowired property is reason for circular dependency.
Eg:
#Autowired
private TestService testService;
(Tips to identified just try to comment and find out which property is reason to break the application)
Once identified just use #Lazy on top of this #Autowired variable.
Eg :
#Lazy
#Autowired
private TestService testService;
And Application worked smoothly.
AsyncConfigurer configuration classes get initialized early in the application context bootstrap. If you need any dependencies on other beans there, make sure to declare them #Lazy as far as possible in order to let them go through other post-processors as well.
Reference JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html
I managed to fix a similar issue by adding #Qualifier together with #Autowire, for example:
#Autowired
#Qualifier("publisher")
private Publisher publisher;

Spring get bean without implementation

I try do all things as here
https://spring.io/guides/gs/accessing-data-jpa/
But i get error, when try repeat this line
ConfigurableApplicationContext context = SpringApplication.run(Application.class);
in my app this seems so
#Autowired
private ConfigurableApplicationContext appContext;
error that i get when call getBean function
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [ru.tcsbank.target.core.service.TestRepository] is defined: expected single bean but found 0:
What is the problem with this example?
There are a number of issues that could be causing this. Code from the TestRepository object would be helpful.
From what you've provided, my best guess is that some object, likely the TestRepository, is being wired in, but is missing the annotation to tell Spring it's a bean. Check that the proper objects have #Entity, #Service, #Component, and #Repository.
You have to add a #Repository annotation to your TestRepository.

Spring+hibernate+jpa how does it work?

In the new project that I have joined, they keep using the terms Hibernate and JPA interchangeably. So, I tried to dive down into the code and try to understand how this whole thing works (I am new to Spring, JPA and Hibernate world). I'll try to put the code here for better understanding:
1) There is a #Configuration class where they have the following:
#Resource
private HibernateJpaVendorAdapter hibernateOracleJpaVendorAdapter;
LocalContainerEntityManagerFactoryBean entityManager =
new LocalContainerEntityManagerFactoryBean();
entityManager.setJpaVendorAdapter(hibernateOracleJpaVendorAdapter);
entityManager.setPersistenceUnitName("abc");
.
.
So, in this configuration class, we are returning an EntityManagerFactory.
2) Then there is a persistor class marked #Persistor, where a method of repository is invoked (for example, for a save operation):
blahblahRepository.save(blahblahEntity, abcdef);
3) Finally there is a repository class which is annotated #Repository. Then again, they have this piece of code:
#PersistenceContext(unitName = "same as the name in persistence.xml")
protected EntityManager entityManager;
The "save" method wraps around the persist method of JPA:
getEntityManager().persist(entityObject);
My questions are as follows:
1) There is no word about Hibernate other than in the hibernateJpaVendorAdapter. I searched the entire workspace and it showed just 3 occurences of the word hibernate, all in the configuration file.
2) From whatever knowledge I have, one should use either an EntityManagerFactory or an EntityManager but we are doing both?
Hibernate is one of the implementations of the JPA spec. Since your project chose Hibernate as its JPA implementation, it uses the JPA API, which delegates the Hibernate. Just like when you use the JDBC API, which delegates to a specific Oracle or PostgreSQL driver.
EntityManagerFactory, as its name indicates, is a factory for EntityManager. I don't see why you wouldn't use both. EntityManager is the main interface of the JPA API, used to execute all database operations (find, persist, merge, query, etc.). EntityManagerFactory must be configured before asking it to create an EntityManager.

Resources