Loading up properties file to a class in Spring - spring

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;

Related

contex:componet-scan not picking up beans defined in jar file

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"/>

Inject property to spring bean using annotation

As explained here and here it is quite clear how to do it but still can't seem to make it work.
I simply like to use the #Value annotation in order to inject a property to a spring bean. I created a basic spring MVC project with one controller and one bean.
Here is my application context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="me.co.fatsecret" />
<!-- Properties -->
<bean id="props"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:fatProperties.properties" />
</bean>
</beans>
I have one bean called Configuration:
package me.co.fatsecret;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class Configuration {
/*--- Members ---*/
#Value("${api_key}")
protected String API_KEY;
#Value("${api_secret}")
protected String API_SECRET;
#Value("${api_url}")
protected String API_URL;
/*--- Constructors ---*/
public Configuration() {
}
/*--- Getters & Setters ---*/
public String getAPI_KEY() {
return API_KEY;
}
public void setAPI_KEY(String aPI_KEY) {
API_KEY = aPI_KEY;
}
public String getAPI_SECRET() {
return API_SECRET;
}
public void setAPI_SECRET(String aPI_SECRET) {
API_SECRET = aPI_SECRET;
}
public String getAPI_URL() {
return API_URL;
}
public void setAPI_URL(String aPI_URL) {
API_URL = aPI_URL;
}
}
Now I have only one controller, injected with this Configuration class and as I call this controller I see that the values in the Configuration class are not populated right.
My properties file is located under the resources folder (src/main/resources) and is a part of my classpath (done by default since this is a maven project). Here it is:
api_url=http://platform.fatsecret.com/js?
api_key=SomeKey
api_secret=SomeSecret
The file name is fatProperties.properties.
As I debug my server when calling the controller I see that the content of the Configuration class is:
${api_key}
${api_secret}
${api_url}
This is the actual value of the Strings, wich means that the vales from the properties file are not getting injected for some reason.
Am I missing something here?
UPDATE1: I replaced the PropertyPlaceholderConfigurer bean with:
<context:property-placeholder location="classpath:fatProperties.properties"/>
Getting the same result
Ok, got it!
I'm using a spring MVC project, which means I have a separated context for my web layer (the controllers). The "Configuration" bean which hods the properties using the #Value annotation is injected to a controller. My property-placeholder is defined within my root-context hence it cannot be seen from my controller. To resolve the issue I simply added the property-placeholder definition to my DispatcherServlet context and it works like a charm :)
Add this to your application context file:
<context:property-placeholder location="classpath:fatProperties.properties" />
Try
#Value("#{props['api_key']}")
private String apiKey;

Spring + Felix war = FileNotFoundException

Is it possible to use spring inside war bundle on felix? I use spring 3.0.5 with felix on glassfish 3.1
I tried to enter component-scan tag inside OSGI war bundle in felix, and I'm getting the below exception.
I saw that a similar bug was solved for Equinox, and what about felix? Is there a workaround or solution to this problem?
P.S: the same exception is thrown if I define path with * in web.xml contextConfigLocation, for example:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/*.xml</param-value>
</context-param>
Exception:
2012-02-08 18:30:23,194 [pool-28-thread-1] (PathMatchingResourcePatternResolver.java:532) WARN - Cannot search for matching files underneath URL [bundle://275.0:2/examples/services/] because it does not correspond to a directory in the file system
java.io.FileNotFoundException: URL [bundle://275.0:2/examples/services/] cannot be resolved to absolute file path because it does not reside in the file system: bundle://275.0:2/examples/services/
at org.springframework.util.ResourceUtils.getFile(Res ourceUtils.java:204)
at org.springframework.core.io.AbstractFileResolvingR esource.getFile(AbstractFileResolvingResource.java :52)
at org.springframework.core.io.UrlResource.getFile(Ur lResource.java:168)
at org.springframework.core.io.support.PathMatchingRe sourcePatternResolver.doFindPathMatchingFileResour ces(PathMatchingResourcePatternResolver.java:528)
...
2012-02-08 18:30:23,194 [pool-28-thread-1] (PathMatchingResourcePatternResolver.java:353) DEBUG - Resolved location pattern [classpath*:examples/services/**/*.class] to resources []
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
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/util http://www.springframework.org/schema/util/spring-util-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">
<context:annotation-config/>
<tx:annotation-driven />
<context:component-scan base-package="examples.services" />
</beans>
thank you for any tip
There are 2 workarounds I found to solve it. Still I'll be glad to hear a real solution for felix.
The workarounds are:
Use equinox instead of felix :)
(an ugly one) Create a temporary folder and extract all the classes into it. Create a class org.eclipse.core.runtime.FileLocator with a function
public static URL resolve(URL url) throws IOException
and return the url of content from this folder, for example:
String path = url.getPath();
String str;
if(path.contains("com")){
str = path.substring(path.indexOf("com"));
}
return new URL("file:\\c:\\temp_classes\\"+str);
A slightly more elegant solution if you don't mind tying yourself to Felix.
package org.eclipse.core.runtime;
import java.net.URL;
import org.apache.felix.framework.BundleRevisionImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
public class FileLocator {
private FileLocator() {}
public static URL resolve(URL url) {
if(url == null) {
return null;
}
Bundle bundle = FrameworkUtil.getBundle(FileLocator.class).getBundleContext().getBundle();
BundleRevisionImpl bundleRevision = bundle.adapt(BundleRevisionImpl.class);
return bundleRevision.getLocalURL(url.getPort(), url.getPath());
}
}
This requires that you export the framework on Felix startup with the following parameter:
-Dorg.osgi.framework.system.packages.extra=org.apache.felix.framework

How to initialized java bean with annotation in spring framework?

I have a Java bean:
public class User{
private Integer userid;
private String username;
private String password;
private boolean enable;
//getter and setter
}
I am able to initialize it as a spring bean at context.xml via:
<context:component-scan base-package="com.myCompany.myProject" />
But I don't want initialize it in xml. How can I initialize it with sring 3 annotation. I tried with the following:
#Component
public class User{
private Integer userid;
private String username;
private String password;
private boolean enable;
//getter and setter
}
But the above did not work for me. Any ideas?
I believe that is because you have enable component scan on the package com.myCompany.myProject and not on the package com.myCompany.myProject.db
Change your scan definition to this : <context:component-scan base-package="com.myCompany.myProject.db" /> (or add a new one, if you want classes from the other package as well) and you can remove the bean definition from XML and have your annotation work for you.
Silly, but still, ensure that the #Component annotation is that of Spring's. I've at times faced this silly issue of defining an annotation that is actually not from the desired library (owing to the same name of the annotation, by different libraries in my classpath).
You need to add
<context:annotation-config />
With this XML my Autowiring works flawless:
<?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:p="http://www.springframework.org/schema/p"
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-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/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.vanilla.example"></context:component-scan>
</beans>
you shouldn't need to have both declared.
Use of context:annotation-config allows for autowiring of beans via annotations etc
Use of context:component-scan provides everything that context:annotation-config, but allows for autodiscovery of beans. The package you supply in context:component-scan will scan that package plus all sub packages.
Hope this helps
Be sure that the "User" class is the package or sub-package of the
"com.myCompany.myProject".
You do NOT need to include <context: annotation-config/>, it is
included with component-scan.
The bean is available with the name "user" by default, unless you
specify the bean name with #Component("myBeanName")
Once that is done, you can autowire the bean into another with:
#Autowired
User user;
OR
#Inject
User user;
NOTES:
#Inject is a javax.inject annotation the injection is NOT required.
#Autowired is a Spring annotation and the injection is required.
#Autowired can be used in one of the following ways:
just above the member variable
constructor that accepts a User bean
setter that accepts a User bean.
I have configured my xml file in this way , this will help you to solve the problem.
For Context-componentscan use
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.java.Controllers"></context:component-scan>
<context:component-scan base-package="com.java.dao"></context:component-scan>
<context:component-scan base-package="com.java.bean"></context:component-scan>
Or else u can use
<context:component-scan base-package="com.java.*"></context:component-scan>
next for annotation driven use
<mvc:annotation-driven />
For resources use this
<mvc:resources location="/" mapping="/**"/>

Adding Xml configurations to a Spring ApplicationContext that is already setup

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.

Resources