I have three projects - proj-a, proj-b, and main such that main depends on proj-a and proj-b.
proj-a and proj-b each contains a module-context.xml and properties file.
proj-a module-context.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">
<context:property-placeholder location="classpath:/META-INF/proj-a.properties"/>
<bean ... someProperty="${property-a}" />
</bean>
proj-a.properties
property-a=hello-a
proj-b's configuration is identical except a is replaced by b.
proj-b module-context.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">
<context:property-placeholder location="classpath:/META-INF/proj-b.properties"/>
<bean ... someProperty="${property-b}" />
</bean>
proj-b.properties
property-b=hello-b
A Class in main wants to create an ApplicationContext that consists of both proj-a and proj-b's module-context.xml. The problem is that only one of the properties file is processed by spring. If proj-a's module-context.xml's loaded first, proj-b's properties file is never read.
The following snippet throws an Exception.
public static void main( String[] args ) throws IOException {
ApplicationContext context = new FileSystemXmlApplicationContext( new String[] {
"../proj-a/src/main/resources/META-INF/spring/module-context.xml",
"../proj-b/src/main/resources/META-INF/spring/module-context.xml"
} );
}
throws
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name '...' defined in file [...\proj-b\src\main\resources\META-INF\spring\module-context.xml]: Could not resolve placeholder 'property-b'
at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:272)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:75)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:624)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:599)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:398)
How can I properly load the properties files? Merging them is not a solution because properties are project specific.
I found a solution - set property ignoreUnresolvablePlaceholders to true.
Related
I am working on a Spring Project:Common that uses a combination of Annotaions and Spring IOC in XML.
I have a common.jar which contains Common classes used by various projects.
And I have another Spring Project:WebService that refers to the beans defined in common.jar.
For some reason beans marked with #Component Annotation in Common.jar are not being picked up by my WebService Project. But all beans defined using <bean id="" class="" /> in Common.jar were picked up.
Below are the code for all files that have necessary configuration. Would really appreciate your help. Thanks in advance.
In Common.jar, 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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<import resource="springConfig/app/AppServices.xml"/> <!-- Beans in this file were loaded. -->
<context:annotation-config/>
<context:component-scan base-package="com.ipd.app1"/> <!-- Beans for all classes under app1 package were NOT loaded -->
</beans>
In Common.jar, AppServices.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="inquireOrderApp" class="com.ipd.app.inquireOrderDetail.InquireOrderDetailAppImpl"/>
</beans>
Common.jar, com.test.app.MyClass
package com.ipd.app1;
#Component("createOrderApp")
public class CreateOrderAppImpl implements CreateOrderApp {
#Override
public CreateOrderResponse processMSSOrder(TransactionContext tx,
CreateOrderRequest createOrderRequest)
throws ApplicationException, Exception {
System.out.println("In App Layer Class CreateOrderAppImpl to ProcessOrder.");
return response;
}
}
WebService Project, IpdService_IPDSoapHTTPPortImpl.java
#WebService(portName = "IpdSoapHTTPPort", serviceName = "IpdService", targetNamespace = "http://ipd.com/ipdIpdweb/", wsdlLocation = "/wsdls/Ipd.wsdl", endpointInterface = "com.ipd.ipdIpdweb.IpdPortType")
#BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
public class IpdService_IpdSoapHTTPPortImpl implements IpdPortType {
ApplicationContext ctx;
public IpdService_IpdSoapHTTPPortImpl() {
this.ctx = AppContext.getCtx();
}
#Override
public void createOrder(WSHeader wsHeader,
CreateOrderRequest createOrderRequest,
Holder<WSResponseHeader> wsResponseHeader,
Holder<CreateOrderResponse> createOrderResponse)
throws WSException {
CreateOrderApp createOrderApp = (CreateOrderApp) ctx.getBean("createOrderApp");
res = createOrderApp.processOrder(tx, createOrderRequest);
res.setResponseCode(BigInteger.valueOf(0));
res.setResponseMessage("Success");
.....
}
}
Please let me know if you need see the code for any other file.
Well add this to applicationContext.xml
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
I am trying to load a property file (.properties) into my class, I am following the example in another thread here: How to read values from properties file? - but it's not working for me.
here's my quick implementation:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config />
<!-- Load up properties -->
<context:component-scan base-package="com.test"/>
<context:property-placeholder location="file:///C:/dev/workspace/test-project/src/main/resources/appconfig.properties"/>
</beans>
TestConfig.java
#Component
public class TestConfig
{
#Value("${test.key1}")
private String key1;
public String getKey1()
{
return key1;
}
}
src/main/resources/appconfig.properties
test.key1=value
test.key2=value
Starting up my tomcat, I see the following in my log:
00:11:41,985 [localhost-startStop-1] INFO PropertyPlaceholderConfigurer - Loading properties file from URL [file:/C:/dev/workspace/test-project/src/main/resources/appconfig.properties]
However, when I do getKey1(), I get "null".
What am I missing?
Question 2: If I use "classpath":
<context:property-placeholder location="classpath:appconfig.properties"/>
Which directory is that referring to? root of WEB-INF/classes?
I hope you are using IDE like Eclipse.
Check if the resources directory is added to the classpath and it includes all the files within it as well , if eclipse you have to add . in the inclusion pattern
build your project and check if the the property file is available in WEB-INF/classes
To answer your second question
classpath:appconfig.properties -Yes spring will look for the file in WEB-INF/classes
This was silly ...
When I get the TestConfig object, I was doing:
TestConfig config = new TestConfig();
config.getKey1();
Which of course the config object is a brand new object and never instantiated (or injected) with anything.
Instead I am injecting it so it got initialized by Spring framework:
#Autowired
private TestConfig config;
I want to fill some fields with the property values using Spring 3.1.1 but the fields always remain null.
Added to the applicationContext.xml
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<util:properties id="props" location="classpath:application.properties" />
application.properties:
myProp=value
java class:
#Value("#{props[myProp]}")
private String myField;
But on bean creation myField is not filled with "value" from the properties file but remains null.
Also tried (without success):
#Value("#{props.myProp}")
private String myField;
and
#Value("#{myProp}")
private String myField;
The application.properties file is found because I got an "file not found" after I moved it.
Here the stacktrace: http://pastebin.com/5A8i5gF8
What do I have to change?
Have you declared or configured your class which has myField class variable into applicationContext.xml?
try with the char $ instead of #
example:
#Value("${myProp}")
private String myField;
You may be missing <context:component-scan/> or <context:annotation-config/> in your application context - it registers a bean called AutowiredAnnotationBeanPostProcessor which actually processes the #Value tag. If it is not there, just add one of the two and it should work.
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<context:annotation-config />
<context:component-scan base-package="my.base.package" />
<util:properties id="props" location="classpath:application.properties" />
... <some beans (transactions, persistence, ws-endpoints) not used by the test class > ....
<cxf:bus>
<cxf:features>
<cxf:logging />
</cxf:features>
</cxf:bus>
</beans>
Sorry for posting new answer but in comments code doesn't get formatted properly.
#Repository
#Qualifier(value = "myStrategy")
public class MyClass implements MyInterface {
#Value("${prop1}")
private String prop1;
MyClass(){
<prop1 is passed to a method to set a config.>
}
I want to look up some properties from JNDI configured in glassfish v3 server. I want to do it using spring. Here is my spring configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<!--
JNDI look ups.
!-->
<jee:jndi-lookup id="properties"
jndi-name="java:comp/env/jndi/ws_properties"
expected-type="java.util.Properties"/>
</beans>
I have mapped jndi/ws_properties in sun-web.xml and web.xml files. Problem is that this lookup always gives me null properties. But if I do it in java code:
try {
InitialContext context = new InitialContext();
properties = (Properties) context.lookup("jndi/ws_properties");
} catch (NamingException e) {
LOGGER.error("", e);
}
It is ok. I see my properties keys and values.
Could somebody tell me where is the problem here?
This is probably because of your "jndi-name" property.
You don't have to put "java:comp/env/" in the name.
The "resource-ref" property defaults to true and unless you set it to false, it will automatically add the java:comp/env to the name.
I was wondering if there is a way to do the following:
have my wep app startup with its servle-context.xml
When, at a certain point, one particular bean in this xml config is instantiated, it will add it's own xml configuration to the application context (or to a child perhaps?).
I'm asking this because I want to pack some functionality in a stand alone library and then reuse it in different projects, so that initializing a bean of this library will load its xml config.
What I wrote is:
public class IrisLibHelper {
ApplicationContext context;
ApplicationContext irisContext;
#Required
#Autowired
public void setContext(ApplicationContext ctx){
this.context = ctx;
ClassPathXmlApplicationContext xap = new ClassPathXmlApplicationContext(ctx);
xap.setConfigLocation("classpath:com/dariodario/irislib/xmldefs/irisconfig.xml");
this.irisContext = xap;
}
public ApplicationContext getIrisContext() {
return irisContext;
}
public void setIrisContext(ApplicationContext irisContext) {
this.irisContext = irisContext;
}
}
and the irisconfig.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- <context:component-scan base-package="com.dariodario"></context:component-scan> -->
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
p:synchronizeOnSession="true" />
<context:component-scan base-package="com.dariodario.iris.controllers"></context:component-scan>
</beans>
The problem is that it doesn't seem to scan the com.dariodario.iris.controllers package, in fact the controllers don't get mapped! (I've logging debugging on and I don't seen anything).
Why not use the tag <import resource="classpath:applicationConfig.xml" /> ? You can load a spring configuration file which is in jar. In a jar, the Spring XML configuration is always at the root. But if not, you can use this notation: <import resource="${configurablePath}/applicationConfig.xml" /> where configurablePath can be reach by a property place holder or other.
I think this way is cleaner than merging two Spring context.