When I put placeholder in web.xml then it is correctly replaced by value defined in catalina.properties or -D param from vm options. But don't work when i put placeholder into xml which is loaded by ContextLoaderListener.
web.xml snippet:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
${placeholder}, <!-- WORKS -->
/WEB-INF/applicationContext.xml <!-- DON'T WORK, WHEN PLACEHOLDER IS DEFINED INSIDE XML -->
</param-value>
</context-param>
Problem solved. Xml defined in contextConfigLocation is loaded by spring and it is required to define bean from class org.springframework.beans.factory.config.PropertyPlaceholderConfigurer. Properties file can be empty. Values will be loaded from catalina.properties or vm options.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:example.properties</value>
</property>
</bean>
Related
I have few parameters in web.xml file to be externalized. Application is in spring 4.0. Is there a spring way to do this?
More precisely, if I define PropertyPlaceholderConfigurer in context file, is there a way to use that for fetching properties in web.xml?
This is what I tried:
In applicationContext.xml:
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property
name="location"
value="classpath:/test.properties" />
<property
name="ignoreUnresolvablePlaceholders"
value="true" />
</bean>
Then in web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
But the below code returns param value as ${app.url}
<init-param>
<param-name>appUrl</param-name>
<param-value>${app.url}</param-value>
</init-param>
This is not possible as web.xml will be loaded before context initialization. The only solution for this is to move these properties to application server specific properties files.
I am using Tomcat and I moved this property to catalina.properties. Now it's working.
I have two files which contain the dataSource definitions. There are /WEB-INF/applicationContext.xml and src/main/resources/hibernateContext.xml
it's my dataSource definition:
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost/fullproject"
p:username="root"
p:password="admin" />
This definition is necessary in every file for using with different services; Can i don't duplicate this code and only definite it only in one place????
Yes, it's possible to factor out commons snippets into dedicated Spring XML file and then include them like this:
<!-- Import shared bean definitions -->
<import resource="classpath:shared.env.xml"/>
Those two "dataSource" beans can be shared. So you only need one definition.
In your web.xml, load the "master" configuration file:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext.xml
classpath*:/hibernateContext.xml
</param-value>
</context-param>
I am creating a war which is going to use a class from a jar file.
Now this jar file has a exposed a bean in its associationApplicationContext.xml which uses the #Required annotation on some of its properties for initialization.
associationApplicationContext.xml
e.g.
<!-- processes #Required annotations-->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
<!-- The client bean to access the association rest web service -->
<bean id="associationClient" class="com.springtest.client.AssociationClientImpl">
<property name="associationRestClient" ref="associationServiceRestClient" />
</bean>
So inside the AssociationClient the property associationRestClient has #Required tag over its setter method.
#Required
public void setAssociationRestClient(final AssociationRestClient associationRestClient) {
this.associationRestClient= associationRestClient;
}
Now, as when I try to use this bean in my war file -
I have already put the jar dependency in pom.xml of war file
Already put the contextConfigLocation in web.xml as
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/associationApplicationContext.xml
</param-value>
</context-param>
Using the bean from inside the war file in another applicationcontext.xml file as
<import resource="classpath:/associationApplicationContext.xml"/>
<bean id="requestHandlerV1"
class="com.springtest.application.RequestHandlerV1">
<property name="associationClient" ref="associationClient"></property>
</bean>
Here the property associationClient is not getting initialized because it is not able to find the reference to bean associationRestClient which is associationServiceRestClient
I am getting
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'associationServiceRestClient' is defined
How can I get the object of associationClient initialized here ?
PS : I cannot change the implementation which uses #Required annotation
Assuming you have the following:
In web.xml:
<!-root application context-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:associationApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>JerseySpringWebApplication</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationcontext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--URl for web service -->
<servlet-mapping>
<servlet-name>JerseySpringWebApplication</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
You don't have to import the associationApplicationContext.xml in applicationcontext.xml as now the root application beans will be visible in applicationcontext.xml. So application Context.xml will be like:
<mvc:annotation-config/>
<bean id="requestHandlerV1" class="com.springtest.application.RequestHandlerV1">
<property name="associationClient" ref="associationClient"></property>
</bean>
*Assuming you are invoking the controller through rest call.
If you still see issue with this, post your log.
In my web.xml I'm declaring a ContextLoaderListener to configure spring application this way:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
In one of my spring configuration xml files, I'm using different beans profile for development and production.
<beans profile="production">
<bean />
</beans
<beans profile="development">
<bean />
</beans
How I could set the default beans profile in the web.xml? is there something similar to the following when using ContextLoaderListener instead of spring servlet:
<init-param>
<param-name>spring.profiles.active</param-name>
<param-value>production</param-value>
</init-param>
You can configure web.xml at the level of ContextLoaderListener with:
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>profileName</param-value>
</context-param>
and the level of DispatcherServlet with:
<init-param>
<param-name>spring.profiles.active</param-name>
<param-value>profileName</param-value>
</init-param>
Reference: http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/
SETUP:
At our company we run multiple sites (many .war files deployed in a single TomCat server). However, most of the .WAR files are identical in the .classes that they use. So we refactored the common classes in to a separate .jar which was then included in each of the .wars.
Now, realizing that all the .war(s) include the same .jar, we decided to further reduce the size of the .war files by removing the duplicated .jar and adding it to the shared.loader in catalina.properties (we are using Tomcat 7).
We left the .war files to only contain configurations specific to each site's configuration.
We are using Spring to help us with wiring classes together.
PROBLEM:
Some classes in the newly refactored .jar file contain #Value annotation. It appears that the #Value annotation is not being "executed" and the value being annotated is never set. If we add the .jar file back into the .war the annotation works and value is set. However, just pulling the .jar out into the shared.loader class path fails to process the #Value annotations.
Interestingly the #Component annotations work fine and the relationships are properly #Autowired, it just that all the #Value annotated fields are null. We are using Sprin 3.1.4.
We are using Spring's PropertyPlaceholderConfigurer to read the property file. The confirurer is created by the applicationContext.xml referenced from the .war.
QUESTION:
Is there a way to fix this while continuing to have the .jar file external to the .war file that depends on it?
CONFIGURATION
Here is the configuration that lives in the .war file. The common .jar file does not have any configuration files:
applicationContext.xml:
-----------------------
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="config" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
</bean>
<!-- Scan for components in .jar -->
<context:component-scan base-package="com.usamp.gozing.comm.service" />
<!-- Scan for components in the .war -->
<context:component-scan base-package="com.springapp.mvc.rest" />
</beans>
Here is the application.properties:
application.hostname="test1eeee33332342341234:-in war"
workflow.rule.name="matched workflow - in war"
The configuration is bootstrapped, by standard web.xml:
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Dynamic ApplicationContext</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.springapp.mvc.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Thanks.
-AP_