Implementing annotation based Spring AspectJ (JavaConfig) - java

We're trying to implement AspectJ #Aspect into our existing software for executing some code after a service call is made.
Note:
We have service interfaces and implementations being #Autowired
throughout the project via rest controllers as well as other service implementations.
This project is entirely a Java Configuration with no XML whatsoever.
We're using Spring 4.1.2 RELEASE deployed on Tomcat 7.0.54.
Issue:
When we added #EnableAspectJAutoProxy into our main #JavaConfig, we experience the following exception:
Unresolvable circular reference.
Which fails every #Autowired attempt on a long list of beans.
Tried:
Removed the #EnableAspectJAutoProxy annotation which autowires everything correctly but our #Aspect never gets invoked.
Added the CGLIB support in the annotation by declaring
proxytargetclass=true to no avail.
We've tried following this documentation directly from Spring: #EnableAspectJAutoProxy Javadoc
This seems to be an issue with AspectJ's proxy mechanism dealing with autowired dependencies.
Why does this occur when we add the #EnableAspectJAutoProxy?
Our Java Config:
#Configuration
#EnableWebMvc
#EnableJpaRepositories(basePackages ={"com.company.product.persistence.repository"})
#EnableTransactionManagement
#EnableSwagger
#EnableAspectJAutoProxy
#PropertySource({"classpath:hibernate.properties",
"classpath:auth.properties",
"classpath:mail.properties",
"classpath:locations.properties"
})
#ComponentScan(basePackages = {"com.company.product"})
public class WebConfig extends WebMvcConfigurerAdapter {
//Bean declarations here.
//Note: All services/repos/controllers are annotation based.
}
Aspect implementation:
#Aspect
#Component
public class PostMessageAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#After("execution(*com.company.product.persistence.serviceImpl.event.eventServiceImpl.methodCall(..))")
public void postMessageRun(final JoinPoint joinPoint) {
logger.info("CALLED AFTER METHOD");
}
}
Update:
Managed to get AOP/AspectJ working perfectly fine on one dev machine only requiring a minor change to our Spring Security config. We are both using Intellij, openJDK 1.7.0_65 on Ubuntu 14.0.4 running on default instances of Tomcat 7.0.56. On the other machine running the same software stack, gets the following.
Stack Trace:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dispatchingMessageController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.event.DispatchingEventService com.apx.efm.controllers.message.DispatchingMessageController.dispatchingEventService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dispatchingEventServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.building.BuildingAd dressesService com.apx.efm.persistence.serviceImpl.event.DispatchingEventServiceImpl.buildingAddressesService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'buildingAddressServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.building.BuildingService com.apx.efm.persistence.serviceImpl.building.BuildingAddressServiceImpl.buildingService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'buildingServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.apx.efm.persistence.service.building.BuildingAddressesService com.apx.efm.persistence.serviceImpl.building.BuildingServiceImpl.buildingAddressesService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'methodSecurityInterceptor' defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.aopalliance.intercept.MethodInterceptor]: Factory method 'methodSecurityInterceptor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.apx.efm.persistence.service.user.EfmUserService com.apx.efm.application.config.SecurityConfig.efmUserService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'efmUserServiceImpl' defined in file [/home/apxdev4/Development/GitRepositories/efim-restful-web-service/target/EFIM/WEB-INF/classes/com/apx/efm/persistence/serviceImpl/user/EfmUserServiceImpl.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'methodSecurityInterceptor': Requested bean is currently in creation: Is there an unresolvable circular reference?

This was entirely an issue with our Spring configuration. Our Spring Security configuration was trying to #Autowired beans while they were still in the middle of being processed by our main application configuration. We solved this by ensuring that Spring Security gets configured after the main #Configuration.
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
// Initialize web mvc
appContext.setDisplayName("APP");
appContext.register(WebConfig.class);
appContext.register(SecurityConfig.class);
// Rest omitted (listeners, dispatcher servlet, etc.)
}

Related

Multiple entityMangagerFactories ( 1PC pattern used) leads to java.lang.IllegalStateException: 'url' not set exception

I have the Spring Maven project using Java 11. Jboss WIldfly 15.0.1 Final is my deployment server.
To import data (objects using Hibernate) from one data source to another data source (MySQL)- I have added one primary entityManagerFactory with JpaTransactionManager and I have 2 other entity manager factories separate perisistenceUnits and a chainedTransactionManager being used(for 1 Phase commit-1PC commnit).
When deploying the war, sometimes, I get the below exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'someDAO': Injection of persistence dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'onetimeConfig': Injection of persistence dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'entityMgrFactory2' defined in class path resource [com/path/ImportConfig.class]: Bean
instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to instantiate
[javax.persistence.EntityManagerFactory]: Factory method 'entityMgrFactory2' threw exception;
nested exception is java.lang.IllegalStateException: 'url' not set
someDAO class header is:
#Transactional(rollbackFor = {Exception.class})
#Repository("someDAO")
public class SomeDAOImpl extends ParentDAOImpl implements SomeDAO {
The someDAO class extends the ParentDAOImpl class in which the primary entityManagerFactory is used and is also mentioned using #DependsOn. So, why does on deploy the creation of someDAO is trying to trigger the creation of entityMgrFactory2 when entityManagerFactory is mentioned in?!
#Repository("parentDAOImpl")
#DependsOn({"entityManagerFactory"})
public class ParentDAOImpl implements ParentDAO, Serializable {
#PersistenceContext
private transient EntityManager entityManager;
...
The problem never replicates on my local machine. It does occurs only while deploying on other servers and deployment fails due to this. And also the exception sometimes mentions someDAO and other times a different DAOclass that extends ParentDAOImpl.
Please help me, I am a novice.

Moved config, entity and other classes

I have a big problem.
I have an application with Spring-Boot and Spring-Data.
It goes well before that i moved some classes and refactory the directory.
I have two database and before i moved classes, i had this config class for a second database:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages="it.phoops.rt.grigliaprocessi.util",
entityManagerFactoryRef = "organoEntityManager",
transactionManagerRef = "organoTransactionManager")
public class OrganoConfig {
#Bean(name = "organoDataSource")
#ConfigurationProperties(prefix="organo.datasource")
public DataSource organoDataSource(){
return DataSourceBuilder.create().build();
}
#Bean(name="organoEntityManager")
public LocalContainerEntityManagerFactoryBean
organoEntityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("organoDataSource") DataSource dataSource){
return
builder.
dataSource(organoDataSource()).
packages("it.phoops.rt.grigliaprocessi.util.entity").
persistenceUnit("organo").build();
}
#Bean("organoTransactionManager")
public PlatformTransactionManager
organoTransactionManager()
{
return new
DataSourceTransactionManager(organoDataSource());
}
}
Now, i moved in "it.phoops.rt.grigliaprocessi.organo" and i change the value of "basePackages" from "it.phoops.rt.grigliaprocessi.util" to "it.phoops.rt.grigliaprocessi.organo" and
the string "it.phoops.rt.grigliaprocessi.util.entity" to it.phoops.rt.grigliaprocessi.organo.entity".
I moved Entity, Service and Repository classes from:
it.phoops.rt.grigliaprocessi.util.controller
it.phoops.rt.grigliaprocessi.util.entity
it.phoops.rt.grigliaprocessi.util.repository
to
it.phoops.rt.grigliaprocessi.organo.controller
it.phoops.rt.grigliaprocessi.organo.entity
it.phoops.rt.grigliaprocessi.organo.repository
But now, i have this error, caused of nested exception:
Caused by: java.lang.IllegalArgumentException: Not a managed type:
class it.phoops.rt.grigliaprocessi.organo.entity.Albero
......
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'alberoRepository': Invocation of init
method failed; nested exception is
java.lang.IllegalArgumentException:
Not a managed type: class
it.phoops.rt.grigliaprocessi.organo.entity.Albero
....
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error
creating bean with name 'alberoService': Unsatisfied dependency
expressed through field 'repo'; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating
bean with name 'alberoRepository': Invocation of init method failed;
nested exception is java.lang.IllegalArgumentException: Not a managed
type: class it.phoops.rt.grigliaprocessi.organo.entity.Albero
....
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error
creating bean with name 'alberoController': Unsatisfied dependency
expressed through field 'alberoService'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error
creating bean with name 'alberoService': Unsatisfied dependency
expressed through field 'repo'; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating
bean with name 'alberoRepository': Invocation of init method failed;
nested exception is java.lang.IllegalArgumentException: Not a managed
type: class it.phoops.rt.grigliaprocessi.organo.entity.Albero
Can you help me ?
Thanks
Change you basepackages declaration from it.phoops.rt.grigliaprocessi.util to it.phoops.rt.grigliaprocessi.organo. Also please check the basepackages in componentScan in your Spring boot main class.

Spring Boot 2.0.3 JDBC session persistance error

I have a working Spring Boot Web application. We want to persist the session to the DB so I followed the spring tutorial, found here and I am getting this error at startup:
Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sessionRepositoryFilterRegistration' defined in class path resource [org/springframework/boot/autoconfigure/session/SessionRepositoryFilterConfiguration.class]: Unsatisfied dependency expressed through method 'sessionRepositoryFilterRegistration' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'org.springframework.boot.autoconfigure.session.JdbcSessionConfiguration$SpringBootJdbcHttpSessionConfiguration': Unsatisfied dependency expressed through method 'setTransactionManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'transactionManager' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'connectionsConfiguration': Unsatisfied dependency expressed through field 'emFactory'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'sessionFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
Here is my connectionsConfiguration class:
#Configuration
public class ConnectionsConfiguration implements ApplicationListener<ApplicationReadyEvent> {
#Autowired
DataSource dataSource;
#Autowired
private EntityManagerFactory emFactory;
#Bean
public EntityManager getEntityManager() {
return emFactory.createEntityManager();
}
#Bean
#Scope("prototype")
public LocalSessionFactoryBean sessionFactory() throws ClassNotFoundException {
LocalSessionFactoryBean fact = new LocalSessionFactoryBean();
fact.setAnnotatedPackages("com.xxx.persistence.model");
fact.setPackagesToScan("com.xxx.persistence.model");
fact.setDataSource(dataSource);
return fact;
}
}
How do I get this to work? Do I need to explicitly define the sessionFactory? I was under the impression that spring would handle this behind the scenes.

How would I execute a stored procedure from an implementation of EmptyInterceptor?

I have an implementation of EmptyInterceptor defined as a #Component that sets some fields on save or update. In certain situations for a delete, I'd like to run a stored procedure before the delete happens. I was trying to use the EntityManager to executed the procedure but I am not able to inject the PersistenceContext using:
#PersistenceContext
private EntityManager entityManager;
This is because my implementation of EmptyInterceptor is #Autowired into my Config class that creates our LocalContainerEntityManagerFactoryBean. The interceptor is used when the entity manager factory is created so I get a circular dependency if I try to inject the EntityManager into the interceptor:
16:07:28,526 WARN [org.springframework.web.context.support.AnnotationConfigWebApplicationContext] (ServerService Thread Pool -- 30) Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private x.y.z.MyInterceptor x.y.z.MyConfig.myInterceptor; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myInterceptor': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'entityManagerFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
16:07:28,535 ERROR [org.springframework.web.context.ContextLoader] (ServerService Thread Pool -- 30) Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private x.y.z.MyInterceptor x.y.z.MyConfig.myInterceptor; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myInterceptor': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'entityManagerFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
If I can't get to the EntityManager to execute my stored procedure, what are my alternatives? I am looking into getting the EntityManager in my Config class and adding it as a field on the interceptor but that seems like it could get nasty.

JUnit returns error creating bean with name 'sessionFactory' defined in URL

I am a newbie to JUnit. To experiment it, I would like to test a repository class of Spring. It has only one method that is used to retrieve rows based on provided id but I am receiving an exception. I've found out one way to solve the issue is to add a context class but I am not sure if that helps, if that does, not sure how to do it. Another question is do I need to run the project when I want to run the testcases?!!
Exception
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(
.........
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Table1RepositoryImpl':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private org.hibernate.SessionFactory com.myproject.repository.Table1RepositoryImpl.sessionFactory; nested
exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in URL
[file:WebContent/WEB-INF/my-servlet.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError:
javax.persistence.OneToMany.orphanRemoval()Z
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(
....
Caused by: org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.hibernate.SessionFactory
com.myproject.repository.Table1RepositoryImpl.sessionFactory; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sessionFactory' defined in URL [file:WebContent/WEB-INF/my-servlet.xml]: Invocation of init method
failed; nested exception is java.lang.NoSuchMethodError:
javax.persistence.OneToMany.orphanRemoval()Z
....
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sessionFactory' defined in URL
[file:WebContent/WEB-INF/my-servlet.xml]: Invocation of init method
failed; nested exception is java.lang.NoSuchMethodError:
javax.persistence.OneToMany.orphanRemoval()Z
......
Caused by: java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2021)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:895)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:728)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3625)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3579)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1381)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1786)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1870)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
... 53 more
JUnit Test Case
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"file:WebContent/WEB-INF/my-servlet.xml"})
public class Table1RepositoryTests {
#Autowired
private Table1Repository table1Repository;
private Table1 table1;
#Before
public void setup(){
table1 = new Table1();
table1.setDescription("This is row 1 of table 1");
table1.setId(1);
}
#Test
public void shouldReturnFirstRowOfTable1(){
Table1 result = table1Repository.retrieveTableById(1);
assertEquals(result,table1);
}
}
Update
It seems like I should inject SessionFactory object. As I have following line in my repository class.
#Autowired
private SessionFactory sessionFactory;
Also I've found following link that says "For example, do not write unit tests that make HTTP requests, access a database, or read from the filesystem." Then how am I supposed to test if my repository code is working?
You can use HSQLDB to test the repository code. HSQLDB can be used as in memory mode, and re-construct each time you run the UnitTest.
IMHO, it's recommended to only test the individual classes. So you'd better mock the sessionFactory and make it return whatever you want in Table1RepositoryTests.
If you really want to test the injection logic of spring, and test Table1RepositoryImpl with sessionFactory, you can use the syntax #RunWith(SpringJUnit4ClassRunner.class) in your code. The exception is because of no such method orphanRemoval. Google it you can find answers in stackoverflow or blog

Categories