Strange Tomcat 8 deployment behaviour - java

When I deploy my Spring 4.0.1.RELEASE web application to Tomcat 8.0.33 installed on ext3 running on Java 1.8.0_92 on Centos 6.7 I get the following error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'qualityAuditTokenService' defined in URL [jar:file:/home/www/webapps/ROOT/WEB-INF/lib/product-service-2.0.1-SNAPSHOT.jar!/com/company/product/services/QualityAuditTokenService.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.company.workflow.dao.TokenDao]: : No qualifying bean of type [com.company.workflow.dao.TokenDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.company.workflow.dao.TokenDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:742)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4811)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5251)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1092)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1834)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.company.workflow.dao.TokenDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1100)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:806)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:734)
... 28 more
However if I install exactly the same web application to Tomcat 8.0.33 installed on an NFS mount running on Java 1.8.0_92 on Centos 6.7 it works just fine. It also works just fine if I install it to Tomcat 7.0.69 on ext3 on Centos, Tomcat 8.0.33 on ext4 on Ubuntu and NTFS on Windows. So it's just throwing this error running in Tomcat 8.0.33 on ext3 on Centos. It wouldn't be so much of a problem if this weren't our live deployment environment.
So this is clearly not one of the standard "missing annotations" or "bean class missing from JAR" type problems although I am happy to hear suggestions in this vein in case I missed something.
The strange thing about this deployment is that the Spring beans are created in a different order on the different file systems. In the versions that work, the following appears in the logfile with Spring logging maxed:
DEBUG DefaultListableBeanFactory:449 - Creating instance of bean 'tokenDaoHbm'
DEBUG DefaultListableBeanFactory:249 - Returning cached instance of singleton bean 'sessionFactory'
DEBUG DefaultListableBeanFactory:249 - Returning cached instance of singleton bean 'searchSessionFactory'
DEBUG DefaultListableBeanFactory:750 - Autowiring by type from bean name 'tokenDaoHbm' via constructor to bean named 'sessionFactory'
DEBUG DefaultListableBeanFactory:523 - Eagerly caching bean 'tokenDaoHbm' to allow for resolving potential circular references
DEBUG DefaultListableBeanFactory:249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG DefaultListableBeanFactory:249 - Returning cached instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor'
DEBUG AnnotationTransactionAttributeSource:108 - Adding transactional method 'TokenDaoHbm.update' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG InfrastructureAdvisorAutoProxyCreator:551 - Creating implicit proxy for bean 'tokenDaoHbm' with 0 common interceptors and 1 specific interceptors
DEBUG JdkDynamicAopProxy:117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.company.product.dao.hibernate.TokenDaoHbm#4a51d9f9]
DEBUG DefaultListableBeanFactory:477 - Finished creating instance of bean 'tokenDaoHbm'
This is the bean that would satisfy the dependency had it been created - in the version that throws the exception, this bean creation is notable for it's absence.
TL;DR
So, how can the OS, file system type and/or network latency change the order which Spring creates beans (or otherwise break it's dependency analysis)? Surely this is something enshrined in the WAR file (and the version of Spring it is packaged with)?
I have tried to influence bean creation via #ComponentScan and #Qualifier to no avail - are there other approaches?
This problem bears a resemblance to the one linked below, but there is no posted solution (and they are having the problem with Tomcat 7 not 8).
Need help debugging Tomcat 7 application error
Any help with this greatly appreciated, as this one is really vexing me! :-D

I now have a solution to this (hence posting an answer) but it's butt fugly and I still have no explanation for why this is necessary (so I'll save the accepted tick for either a more elegant solution or a complete explanation).
It turns out my issue is related to issue 57129 raised on the ASF bugzilla:
https://bz.apache.org/bugzilla/show_bug.cgi?id=57129
However, in the case outlined there, multiple JAR files within a WAR contain different versions of the same class file. This means changing the order will change the application behaviour - not desirable.
In my case, the class in question, TokenDaoHbm, only exists once in the WAR file. It's just that, if the Tomcat class loader hasn't loaded the product-dao-hibernate-2.0.1-SNAPSHOT JAR file by the time Spring comes to instantiate qualityAuditTokenService bean, then you get a NoSuchBeanDefinitionException. Surely Spring and/or Tomcat must know all classes must be loaded before bean instantiation can commence?
So, to fix my problem, I placed the following in my application context.xml in the WAR according to the advice from Mark Thomas in the ASF bug posting:
<Resources>
<PreResources className="org.apache.catalina.webresources.FileResourceSet"
base="${catalina.base}/webapps/ROOT/WEB-INF/lib/product-dao-hibernate-2.0.1-SNAPSHOT.jar"
webAppMount="/WEB-INF/lib/product-dao-hibernate-2.0.1-SNAPSHOT.jar" />
</Resources>
If anyone can shed further light on this I am happy to mark them as the accepted answer.

Related

Ehcache 2 maven dependency

In my pom i have ehcache 2 dependency
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache.version}</version>
</dependency>
The problem is that during application build we have a grype check for vulnerabilities and it detects couple of libraries inside this dependency:
NAME INSTALLED FIXED-IN VULNERABILITY SEVERITY
jackson-databind 2.11.1 2.12.6.1 GHSA-57j2-w4cx-62h2 High
jersey-common 2.31 2.34 GHSA-c43q-5hpj-4crv Medium
jetty-server 9.4.39.v20210325 9.4.41 GHSA-m6cp-vxjx-65j6 Low
It is a bit confusing because libraries added to ehcache jar in really strange way - not like dependencies but files with extension *.class_terracotta in folder "rest-management-private-classpath" which is shown on
screenshot
Because of this approach libraries versions can not be overridden or excluded in pom file.
Probably proper approach would be to migrate from ehcache 2 to 3, but it might take some time and i'm wondering if there are any fast solution to exclude this libraries from ehcache jar or override their version?
P.S.
When i check ehcache doc it says that dependency should be added with type pom
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.4</version>
<type>pom</type>
</dependency>
but if i change it to this type in my pom - cache manager in not initialized and i'm getting this error
Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: 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.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: 'entityManagerFactory' depends on missing bean 'cacheManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cacheManager' available
Sometimes library artifacts are released in multiple ways.
One way packages all needed dependencies so it can be used as-is without addition of extra dependencies. The challenge with that is just what you observed here - those embedded dependencies cannot be excluded or changed. org.hamcrest:hamcrest-all is an example.
Some libraries also have a "lighter" version - one containing just the classes etc. for that specific artifact. Then, we can explicitly add other dependencies to get the desired functionality - and we are fully in control of what versions etc. are used. org.hamcrest:hamcrest-core and org.hamcrest:hamcrest-library are partial replacements for hamcrest-all (more dependencies are likely needed to get the complete functionality provided by the -all version).
Personally I much prefer the second way because issues like the one encountered are tricky to find and debug.
So, the fix here is to see if there is a "light" version of Ehcache version 2 and switch to it (along with any other dependencies you need for core functionality) instead.
If there isn't one, and you absolutely cannot switch to version 3, then you could pursue using the maven-shade-plugin to rebuild the ehcache jar, filtering out the extra dependencies. I would highly suggest against this, as who wants to rebuild the ehcache jars with every version update? And it's possible if not likely that the (now mangled) library won't work properly anyway. Plus it would have to be manually uploaded to the team's artifact repository, ideally with a classifier or a different group ID to make it clear that this is not the official release. And if all of this is making your head spin, that's a great justification for doing the upgrade. :)

Spring and MyBatis cannot find bean via MapperScannerConfigurer if interface inside .jar

I'm using Spring 3.2.0 in a legacy project with Mybatis 3.3.0 and Mybatis Spring 1.2.3.
I have several projects that use this technology and they need to have similar new code added to a library that will allow me to interact with an outside system, and during this interaction I need to call several methods in the database in this new code.
I created an interface and put it in a package, say:
com.mycompany.myapp.dao.MyNewService
That interface has a few methods. All of those are defined in a Mybatis mapper file, MyNewService.xml in that same package path.
I create a .jar file of all this code.
In my main application, I added a dependency to this .jar file and it ends up inside of WEB-INF\lib\MyHelpers.jar
In that application, I have a root application context spring file and I attempt to use a mybatis MapperScannerConfigurer to find this new bean/service via:
<!--scan for mappers and let them be autowired -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mycompany.myapp.dao" />
<property name="sqlSessionFactoryBeanName"
value="sqlSessionFactory" />
</bean>
When I run this code, it appears that it cannot find this service in that package path which I know is in WEB-INF\lib\MyHelpers.jar.
The application produces a warning on startup:
WARN (ClassPathMapperScanner.java:167) - No MyBatis mapper was
found in '[com.mycompany.myapp.dao]' package.
Please check your configuration.
The code later fails during dependency injection with a massive stacktrace which essentially says:
2017-03-08 15:38:39,625 [[ACTIVE] ExecuteThread: '0' for queue:
'weblogic.kernel.Default (self-tuning)'] ERROR
(org.springframework.web.servlet.DispatcherServlet:466) - Context
initialization failed
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'orderDetailsController': Injection of
autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.mycompany.myapp.dao.MyNewService
com.mycompany.otherapp.controller.OrderDetailsController.myNewService
; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
matching bean of type [com.mycompany.myapp.dao.MyNewService ] found
for dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
If I dig into that Mybatis code, its simply not finding the resource from the package path inside that .jar when it's using some ResourceResolver code. IF I move my code into my project directly rather than adding the .jar dependency, the code works fine without error.
The concern of course is that I have to put this same code across six projects, so I thought I'd have it in this .jar file and use the MapperScannerConfigurer. We use that in all the projects but all the .xml is within the applications WEB-INF\classes when deployed, it is not inside a .jar file within WEB-INF\lib.
Any ideas how to accomplish this? In summary, it would be akin to:
Making a file called Model.jar based on Mybatis interfaces and .xml mapper files
Adding this as a dependency that appears in WEB-INF\lib
configuring the main spring applicationContext file using the syntax I have above.
If you need more clarification, I can certainly add it.

When upgrading to mule-module-redis-3.4.0, get BeanCreationException: Could not autowire method...RedisModule.set(...)

We've been using mule-module-redis-3.3.3-SNAPSHOT in production with mule 3.4.2 (standalone EE) for about two years now; works great, thanks!
With mule-module-redis-3.4.0, our project's maven compile is ok (yes, we've refactored our code to use the different parameter signatures in some of the RedisModule methods).
But we have been stymied so far with following error below when running any integration test within the maven build. (Our integration test classes simply extend mule's FunctionalTestCase class.)
The one difference we've noticed for the redis-connector 3.4.0 is the RedisModule.set() method has an #Inject annotation; wondering if there could be some dependency conflict or missing dependency/configuration we might be missing?
"... Error creating bean with name 'globalredis': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public byte[] org.mule.module.redis.RedisModule.set(java.lang.String,java.lang.Integer,boolean,java.lang.String,org.mule.api.MuleEvent); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [java.lang.String] is defined: expected single matching bean but found 3: applicationVersion,mysqlPort,testConversionSendToBillingEnabled (org.mule.api.lifecycle.InitialisationException)"
[I've had good suggestions, without success so far :( on the Mule Community Forum with this issue, so hoping there might be others more involved with the mule redis-connector who are here. Thanks!]

Cannot inject EJB specified in applicationcontext.xml in jboss 7

I'm trying to migrate my Java EE application from jboss 5.1 to jboss 7.1 and getting a deployment error.
My EAR has 2 EJB modules and 1 WAR module. both EJB modules gets deployed without any issue. but when i'm trying to deploy with the WAR module it says
Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name "className" Injection of resource fields failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'java:global/ear/ejb/FacadeBean!com.ejb.business.SearchFacade' is defined: not found in JNDI environment
because of copyright issues i'm unable to disclose the full class names. but "classname" is defined as a bean in my spring application context file and it has a dependency injection of SearchFacade which again has some dependencies.
whats confusing is that in the jboss log it shows that SearchFacade is deployed without any issues.
i'm finding so hard to find a solution for this issue. any help will be greatly appreciated.
thanks in advance.
Looks like spring is not able to determine that the EJB component is in that EJB Jar and you need to enforce that the components in that EJB jar are initialized and started before the components in you WAR.
Did you tried to set element into your application*xml and see if that helped?
Something like this in your application.xml
<application-name>EAR</application-name>
<initialize-in-order>true</initialize-in-order>
<module><ejb>EJB.jar</ejb></module>
<module><web><web-uri>WAR.war</web-uri><context-root>....

Spring Roo (STS) - Error creating bean with name 'transactionManager'

I ran into a problem trying to use Spring-roo in STS ide.
I created a project and added EclipseLink ORM, and that is about it.
In persistence.xml i added all the details for the database connectivity.
When I tried to run the spring project, it failed to show the default jspx page i was expecting.
Here is the error:
2012-07-02 10:45:39,411 [pool-2-thread-1] ERROR org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in file [/home/ubuntu/springsource/vfabric-tc-server-developer-2.7.0.RELEASE/spring-insight-instance/wtpwebapps/SpringRooStats/WEB-INF/classes/META-INF/spring/applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in file [/home/ubuntu/springsource/vfabric-tc-server-developer-2.7.0.RELEASE/spring-insight-instance/wtpwebapps/SpringRooStats/WEB-INF/classes/META-INF/spring/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.reflect.UndeclaredThrowableException
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
It is complaining it seems that it needs to create an entity manager, but I think that
it should not since it should run a project that does not connect to a database and just run a simple jspx page.
Does one need to go thru the whole thing with entities just to run a simple project.
Hope someone can help.
Your applicationcontext.xml has a transactionManager defined. This needs a entity manager. Your would need to remove the transaction manager or add the entity manager.
I'm also not sure why you added the ORM framework if your not going to use it.

Categories

Resources