I have a spring-hibernate feature built as a separate jar (Collection.jar) for use by multiple webapps. This collection.jar has a spring-config.xml where beans are defined. When this jar is included in a webapp (spring-application1), the classes defined in collection.jar are not getting auto-wired.
spring-config.xml from Collection.jar
<context:annotation-config/>
<context:component-scan base-package="com.antk.pkg" />
<import resource="spring-datasource.xml" />
<bean id="delegator" class="com.antk.pkg.Delegator">
<property name="dbUtils" ref="dbUtils" />
</bean>
<bean id="dbUtils" class="com.antk.pkg.util.DBUtils">
<property name="dao" ref="collectorDao" />
</bean>
<bean id="collector" class="com.antk.pkg.Collector">
<property name="collectorService" ref="collectorServiceImpl" />
</bean>
<bean id="collectorServiceImpl" class="com.antk.pkg.service.CollectorService">
<property name="collectorDao" ref="collectorDaoImpl" />
<property name="delegator" ref="delegator" />
</bean>
...
and in spring-application1, I am including the above as :
<bean id="com.antk.pkg.collector.spring"
class="org.springframework.context.support.ClassPathXmlApplicationContext" abstract="false"
scope="prototype" lazy-init="default" autowire="default">
<constructor-arg>
<list>
<value>spring-config.xml</value>
</list>
</constructor-arg>
</bean>
But when I call collector, collectorservice is being set as null all the time. Its not getting autowired. Any thoughts.
Assuming your spring-config.xml to be present in your classpath.
Put below in your web.xml -
1) Specify which spring config files to load
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-config.xml</param-value>
</context-param>
2) Define the ContextLoaderListener :-
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Also there is a problem while loading spring-config.xml files from jar.
" Resource implementation supports resolution as java.io.File if the class path resource resides in the file system, but not for classpath resources which reside in a jar and have not been expanded (by the servlet engine, or whatever the environment is) to the filesystem." http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html
Avoid relying on classpath resource loader while loading config.xml files from jar.
Related
Ok, I have been fighting this too long, time to ask for help. HELP!!!
I'm deploying an indipendent jar maven project that will be used as dependency into other projects.
I need that this jar loads its own properties file ("versione.properties" released inside the jar) when the application that will use it, will start up but I want that the application doesn't care about it. This should be in charge on the lib.
I want that who will use this lib, will have just to
include the right dependency inside his pom.xml
add <import resource="classpath*:*-context.xml" /> inside his spring app-context.xml to be sure to include also the lib-context.xml during the spring-context initialization
For this reason, the jar has its own spring lib-context.xml file as the following:
<context:component-scan base-package="it.eng.inps.comppsr" />
<bean id="propertyPlaceholderConfigurer2" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false" />
<property name="locations">
<list>
<value>classpath:versione.properties</value>
</list>
</property>
</bean>
<bean id="version" class="it.eng.inps.comppsr.util.Versione">
<property name="buildVersion" value="${comppsrutil.build.version}"/>
<property name="buildDate" value="${comppsrutil.build.timestamp}"/>
</bean>
As you can immagine, "versione.properties" file contains comppsrutil.build.version and comppsrutil.build.timestamp.
During my tests, I've tried also <value>classpath*:versione.properties</value>, <value>classpath:/versione.properties</value> and <value>classpath:*/versione.properties</value> but with no luck.
This library is used by a web-service application (a war inside an ear file) and this application has got its own spring app-context.xml that loads it own properties file as described by the following code snippet
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="lookupPropertiesInitializer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchSystemEnvironment" value="true" />
<property name="ignoreResourceNotFound" value="false" />
<property name="locations">
<list>
<value>file:///#{lookupPropertiesInitializer.pathToProperties}</value>
<value>classpath*:version.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="it.eng.inps.util, it.eng.inps.comppsr" />
<import resource="classpath*:*-context.xml" />
When I start the application (it runs inside JBoss EAP 7.3), I get this error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'comppsrutil.build.version' in value "${comppsrutil.build.version}"
So, it seems that something goes wrong within the lib initialization.
If I rename the "versione.properties" file in "version.properties" (so with the same name used by the app properties file), this error desappear, I think, because it is loaded by the application PropertyPlaceholderConfigurer, so the lib property file is well located.
For this reason I think that the bean propertyPlaceholderConfigurer2 defined inside lib-context.xml, doesn't work as I expected but I didn't understand why.
Does anyone give me any tips?
I have two modules in my applications:
core
web
The core module contains the following property place-holder configuration in the spring/applicationContext-core.xml context:
<bean id="coreProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:/properties/*.properties</value>
<value>classpath:/profiles/${build.profile.id}/properties/*.properties</value>
<value>file:${ui.home}/profiles/${build.profile.id}/properties/*.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="false"/>
<property name="properties" ref="coreProperties" />
</bean>
<bean id="propertySourcesPlaceholderConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
Considering I have the following property:
resource.suffix=.min
If I inject this value in a core #Component:
#Value("${resource.suffix}")
private String resourceSuffix;
The property is properly resolved .
But, if I add the same configuration in a bean inside the web module, which simply loads the core configurations as well:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet-context.xml /WEB-INF/application-security.xml
classpath*:/spring/applicationContext-core.xml</param-value>
</context-param>
then the property is not resolved and the resourceSuffix value is set to the following String literal value ${resource.suffix.
What am I missing?
I believe this has to do with how spring works with pre/post processors.
Basically you can have duplicated definition or use a different mechanism for loading properties.
As much as I know before spring 3.1 duplication is the only way.
More on http://www.baeldung.com/2012/02/06/properties-with-spring/#parent-child
I've got a strange problem which I think is Spring related. I'm developing a Maven multi module application structured as follow:
DataModule (includes generale Hibernate entities and daos)
ServiceModule (includes specific Hibernate entities and daos) - depends on DataModule
Web (gwt web module) - depends on ServiceModule
In DataModule I've a classic Spring-Hibernate xml configuration, consisting of (relevant code):
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ..>
<!-- Auto scan the components -->
<context:annotation-config />
<context:component-scan base-package="com.x.dataModule" >
<context:include-filter type="regex"
expression="com.x.dataModule.dao.*" />
</context:component-scan>
<!-- Import resources -->
<import resource="applicationContext-hibernate.xml" />
<import resource="applicationContext-dataSource.xml" />
</beans>
applicationContext-hibernate.xml
<beans ..>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean ">
<property name="packagesToScan" value="com.x.dataModel.model.**.*"></property>
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="lobHandler" ref="defaultLobHandler" />
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.query.substitutions">true 1, false 0</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.connection.charSet">UTF8</prop>
</props>
</property>
</bean>
<!-- Transaction Manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
Hibernate.cfg is actually empty, since I aim to avoid explicit mapping due the use of packagesToScan property. applicationContext-dataSource is not relevant since it contains ds configuration.
The ServiceModule relies on the previous module.
applicationContext.xml
<beans ...>
<!-- Auto scan the components -->
<context:include-filter type="regex"
expression="com.x.serviceModule.dao.*" />
<context:include-filter type="regex"
expression="com.x.serviceModule.manager.*" />
<!-- Import resources -->
<context:property-override location="classpath:override.properties"/>
<import resource="classpath*:/applicationContext-hibernate.xml" />
<import resource="classpath*:/applicationContext-dataSource.xml" />
</beans>
The file override.properties contains the following entry, to modify the definition of packagesToScan
sessionFactory.packagesToScan=com.x.*.model.**.*
At this point everything works just fine. The serviceManagers (singletons) are loaded from the factory as
ApplicationContext appContext = new ClassPathXmlApplicationContext(
"applicationContext.xml").getBean(..);
And everything is behaving as expected.
Last part, the Web Module. If I import the ServiceModule and test it as a Java application, again everything is fine. However, if I start the module as a web application, it fails complaining that it's not able to load entities/daos defined in the DataModule.
Relevant files in Web Module:
WEB-INF/spring
applicationContext.xml: nothing here other than the import of applicationContext-security.xml (residing in the same directory)
web.xml
<!-- Spring context -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/spring/applicationContext.xml
</param-value>
</context-param>
<!-- Creates the Spring Container -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
The only way to avoid the problem is to declare explicitly the entities mapping and daos definition in the DataModule xml files.
My question: is there a way to avoid such declarations, and rely entirely on the component/package scan also in Web Module?
I'm not really sure but looks like that somehow the spring web context is conflicting with my other spring context. Otherwise, I don't understand why everything is fine as Java application, but fails as web.
Also (not sure if relevant) it seems that the Session Factory bean is istantiated twice during the process (shouldn't it be a singleton?).
Spring version is 3.1.1 Release, Hibernate 3.6.0 Final (4.0.1 for commons-annotations). Tomcat 7 for deploy.
I didn't provide the Java code of entities/daos/managers since I don't think it's relevant for the question; however, I can provide it if it's of any help. Thanks a lot
I have three xml files in my spring hibernate app
Spring-Security.xml
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
</security:authentication-provider>
</security:authentication-manager>
<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
<!-- A custom service where Spring will retrieve users and their corresponding access levels -->
<bean id="customUserDetailsService" class="com.vaannila.service.CustomUserDetailsService" >
</bean>
hibernate-context.xml
enter code here
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}"
p:user="${app.jdbc.username}"
p:password="${app.jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" />
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<bean id="registrationDAO" class="com.vaannila.dao.RegistrationDAOimpl" >
<constructor-arg ref="sessionFactory"/>
</bean>
Now in my spring security i want something like
<bean id="customUserDetailsService" class="com.vaannila.service.CustomUserDetailsService" >
<constructor-arg ref="registrationDAO"/>
</bean
but my registrationDAO is in hibernate-config and when i do that in spring Security it says no bean named registration DAO
Spring supports reading application context across external jars. Simply add "classpath:" prefix to the context file name. Spring will look for it in the whole project.
For instance, if you are creating web application, you might declare your business logic application context like this (web.xml)
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml <!-- tell Spring to look for context defined on the classpath -->
</param-value>
</context-param>
That way You'll be able to use as many context, as necessary.
On my web.xml I have a "springmvc" servlet declaration (which has a corresponding springmvc-servlet.xml)
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/myapp/*</url-pattern>
</servlet-mapping>
I also have my usual applicationContext.xml file.
Which one gets loaded first? The springmvc-servlet.xml or the applicationContext.xml?
The reason I'm asking this is whenever I place the <mvc:annotation-driven/> element in the applicationContext.xml, I get a Severe Context error. But when I put that element in the springmvc-servlet.xml, my web app runs fine.
Any ideas why?
On another web-app, I have the <mvc:annotation-driven/> inside the applicationContext.xml and it runs fine.
Addendum:
I do notice that the presence of aop:config poses conflict against mvc:annotation-driven
the applicationContext.xml context is parent to the dispatcher-servlet.xml context. I don't know whether this means it is loaded first, but it does not matter in your case:
<mvc:annotation-driven /> must be in the dispatcher-servlet.xml, because it belongs to the web-part of the application.
I solved my problem!
It turns out it has nothing to do with the load order or where the <mvc:annotation-driven/> is declared.
I tried deploying my web-app on another Tomcat and to my surprise there's a stack trace in the localhost log. I had a hint by trial and error that the conflict is with <aop:config/>. But what particular conflict?
Then I saw this error in the log file:
java.lang.ClassCastException: org.aspectj.weaver.ResolvedType$Array cannot be cast to org.aspectj.weaver.ReferenceType
So we have a cast exception. I googled that exact error above and found this: Spring 3: adding causes ClassCastException
It appears the thread starter and I have the same exact issue. So I downloaded the aspectj-1.6.10.jar but I was still missing a class. Then it turns out it should be the aspectjweaver-1.6.9
I was still using a very old aspectjweaver. It didn't have any version on its name. Problem solved. Case closed.
By the way as a bonus, I've manually unrolled the <mvc:annotation-driven/> element to its equivalent xml declaration:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="0" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="validator" ref="validator" />
</bean>
</property>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
They're exactly the same when you declare the <mvc:annotation-driven/> based on what I've researched.
Thanks to everybody who helped me out.
Except for web.xml there is no predefined order.
This happens:
web.xml is loaded by the servlet engine, this triggers the load of all defined servlets, filters, listeners,
the ContextLoaderListener loads the
root application context XML, this
might include a bean definition for a
LocalSessionFactoryBean, triggering
the load of all Hibernate mapping XML
files
the DispatcherServlet loads the web
application context XML
Study the web.xml to determine the order in each case.
see also:
link
You probably have to add the mvc namespace to the application context:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
>
(other namespaces stripped)