I have a properties object having key and value need to set into spring context. which a bean is having a variable as #Value(${key}).
There is no property file in the web application.
Can someone please help on this.
You have to use the #Resource annotation to bind a properties file into Java.
#Resource (name="propertiesMapName")
public Properties someProps;
In your XML files
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd
...
<util:properties id="propertiesMapName" location="classpath:yourFile.properties"/>
Related
Currently learning to build spring apps. I have been quite sucessful deploying mock applications for now, but one thing has been annoying me, which is not understanding the mechanisms behind the numerous annotations we add to the code. Look, I'm not saying I don't know which purpose they serve, where they act, nor am I questioning their helpfulness.
My point is that I feel that skipping the changes that should be made (or are being made?) in the XML files actually makes me feel that at the end of the day I don't know what I am truly writing. Let me be more specific, so you could answer me with regards to the following example. This is from Spring manual.
Let’s assume we have the following configuration that defines firstMovieCatalog as the primary MovieCatalog
#Configuration
public class MovieConfiguration {
#Bean
#Primary
public MovieCatalog firstMovieCatalog() { ... }
#Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
With such configuration, the following MovieRecommender will be autowired with the
firstMovieCatalog.
public class MovieRecommender {
#Autowired
private MovieCatalog movieCatalog;
// ...
}
The corresponding bean definitions appear as follows.
<?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"
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">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
Okay, so, I think if you can answer me 2 questions regarding this example, It would clear a lot the understanding I am lacking here.
The first thing that is not clear for me: is the annotation process a SEPARATED process from the XML configuration, or is it GENERATING this equivalent XML configuration in some hidden fashion?
Where actually IS this XML configuration file? All spring applications I generated through Initializr just generate the pom.xml file, and it does not include configuration. If I were not using the annotations, would I have to manually write an equivalent configuration in the pom?
is the annotation process a SEPARATED process from the XML configuration, or is it GENERATING this equivalent XML configuration in some hidden fashion?
Spring is not generating any XML or annotation in any case. Spring use XML and annotation processing to get info about which components (classes) are available to use and which beans (instances) to create, inject and use for processing. Then, all these beans could be retrieved by application context (not to confuse with xml of the same name).
Where actually IS this XML configuration file?
Spring first version used XML to configure your app. Later (starting in Spring 3), Spring added annotation support and processing to ease application configuration. Annotations are just another way to configure your components and beans without the hassle of maintaining big XML files (over 1000 lines or even more) or just to avoid dealing with XML at all. Current Spring versions support both configurations, you could also use a mix: using XML and using annotations.
Note that Spring's ApplicationContext has several implementations with different entry points for configuration:
AnnotationConfigApplicationContext accepts a class decorated with #Configuration.
ClassPathXmlApplicationContext accepts the path of a XML file available in application classpath.
If I were not using the annotations, would I have to manually write an equivalent configuration in the pom?
First thing first: POM files are for maven processing, not for Spring. Since you're using Maven, and you want to try using a Spring Boot application without annotations, then you can have this project structure:
- src
- main
- java
/* your Java packages and files */
- com.example
+ App <--- Main entry point
- com.example.service
+ Car <--- Component 1
+ Engine <--- Component 2
- resources
+ my-beans.xml <--- XML configuration. Name can be anything
App class:
package com.example;
import com.example.service.Car;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
#Configuration
#ImportResource("classpath:my-beans.xml")
public class App {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(App.class, args);
Car car = ctx.getBean(Car.class);
car.move();
}
}
Car.class:
package com.example.service;
public class Car {
private Engine engine;
public void move() {
engine.start();
}
}
Engine.class:
package com.example.service;
public class Engine {
public void start() {
System.out.println("engine starts");
}
}
my-beans.xml file:
<?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"
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">
<bean class="com.example.service.Engine" />
<bean class="com.example.service.Car" />
<property name="engine" ref="engine"></property>
</bean>
</beans>
is the annotation process a SEPARATED process from the XML configuration, or is it GENERATING this equivalent XML configuration in some hidden fashion
When you initialize a Spring application, you instantiate an ApplicationContext: it's responsible to load all the context definition (the beans, services...).
ApplicationContext is actually an interface which has several implementations depending on how your context is defined:
ClassPathXmlApplicationContext which reads an XML file
AnnotationConfigApplicationContext for annotations based approach
...
Thus you can see it as a unique process, only the datasource is different: either XML or annotations. But they describe the same thing: a context.
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-2.5.xsd">
<import resource="classpath:context2.xml"/>
<import resource="classpath:context3.xml" />
Here Context1.xml is getting over written by context2.xml, context 1.xml and context2.xml are both MDB's. context3.xml is not having issues.
COntext 1 and context2 have some same Bean ID's but have different properties and references.
I found the solution . I was using same Bean ID and thought that it was a pre defined bean ID. I did not have much knowledge on spring . So i studied a bit and found out that u can give any bean ID u want for the class which you are referring to.
I am setting properties using:
<context:property-placeholder location="#{ T(System).getenv().get('DEV_PROPERTIES') ?: 'classpath:/META-INF/properties/config.properties' }"/>
I am able to access the properties:
#Value("${hostname}")
String hostname;`
This works fine.
However, i would like to access the properties using the property map or simple just get the values in a method which can't use #Value variables. Is there a way i can inject the property bean set using <context:property-placeholder />.?
Environment doesn't have the access to properties set from the properties file, it only can read properties from system and environment properties.
No you cannot access the properties used internally by the property-placeholder. What you can do is load the properties into a Properties object and inject that into the property-placeholder and also inject it into whatever you like.
Another tip you don't need to use SpEL to achieve what you want in your location attribute, a simple placeholder would do the trick.
To load a properties object use the util namespace.
<util:properties id="props" location="${DEV_PROPERTIES:classpath:/META-INF/properties/config.properties}" />
<context:property-placeholder properties-ref="props" />
To make the properties you want available to the Environment you should use the #PropertySource annotation on a #Configuration class.
#Configuration
#PropertySource("${DEV_PROPERTIES:classpath:/META-INF/properties/config.properties}")
public class ApplicationConfig { ... }
You can either add this as a bean to your xml file or have it detected while component scanning. Either way should work.
If I have 2 .properties files setup in my Spring XML as so:
<util:properties id="serverProperties" location="file:./applications/MyApplication/server.properties"/>
<util:properties id="someConfig" location="file:./applications/MyApplication/config.properties"/>
How can I inject via annotations these properties files into a bean with java.util.Properties?
How can I grab specific properties via Spring annotations?
Cheers!
#Autowired
#Qualifier("serverProperties")
private Properties serverProperties;
#Autowired
#Qualifier("someConfig")
private Properties otherProperties;
or
#Resource(name = "serverProperties")
private Properties serverProperties;
#Resource(name = "someConfig")
private Properties otherProperties;
Typically, #Autowired is used for by-type autowiring in Spring, and #Resource is used for by-name. #Autowired+#Qualifier can double as by-name autowiring, but it's really meant for by-type autowiring with the ability to fine-tune the type.
As this question has a lot of hits. I thought it would be worthwhile to point out another option using SpEL (Spring Expression Language) - if you need specific properties they can be injected using the #Value annotation on specific bean properties;
class SomeClass {
#Value("#{serverProperties['com.svr.prop']}")
private String aServerCfgProperty;
#Value("#{someConfig['another.config.setting']}")
private String someOtherProperty;
}
You dont need to use the indexing syntax ['index.val'] you can just get it directly;
#Value("#{someConfig}")
private Properties someConfig
#Value("#{serverProperties}")
private Properties svrProps;
I have found this rather useful and moved away from using the properties object directly injected via #Resource/#Autowired.
Another nice reason for using the #Value with an indexed Properties object is that some IDEs (e.g. IntelliJ) can refactor the actual property names if you also have the .properties file in the project which is nice. Another tip is to use something like EProperties (which extends the native Java Properties object) if you want to do inclusion/nesting/substitution in properties files without using Spring's PropertiesPlaceholderConfigurer class (which sadly doesnt expose its properties - to use SpEL indexing ['key'] the bean needs to be an instance of Map<> i.e. extend map which the Java Properties object does)...
Finally, another neat feature with SpEL is you can access properties of beans directly. So say for example if SomeClass in the example above was a Spring bean e.g. someClass then in AnotherBeanClass we could have;
#Value("#{someClass.someOtherProperty}")
private String injectedBeanProp
You could also call a getter method:
#Value("#{someClass.getSomeOtherProperty()}")
private String injectedBeanProp
See the SpEL guide here; http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#expressions
You can use #PropertySource
#Configuration
#PropertySource(name = "someName", value = {"classpath:a.properties", "classpath:b.properties"})
public class MyConfiguration {
}
XMl file
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<context:component-scan base-package="com.sha.home" />
<mvc:annotation-driven/>
<util:properties id="dbProp" location="classpath:db.properties" />
<!-- <context:property-placeholder location="classpath:db.properties"/> -->
</beans>
in java file
#Value("#{dbProp}")
private Properties dbProperties;
System.out.println("urllll"+dbProperties.getProperty("jdbc.url"));
Most of time I encapsulate all properties in to a one utility and used in my apps. In that way you don't need to worry/manage each properties file in app layer. Autowired setProps(...) reads all you loaded util:properties in to the props list.
import java.util.List;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class AppProperiesProcessor {
private List<Properties> props;
private Properties mergedProperties;
#Autowired
public final void setProps(List<Properties> props) {
this.props = props;
}
public String getProp(final String keyVal) {
if (null == this.mergedProperties) {
this.mergedProperties = new Properties();
for (Properties prop : this.props) {
this.mergedProperties.putAll(prop);
}
}
return mergedProperties.getProperty(keyVal);
}
}
I need to access a bean from another bean in Spring. The obvious solution to this, that I know of, is to use the ref tag in the spring config file. But let's say I am not able to modify the spring config file. Is there another way to access beans within other beans?
A few options:
use annotations - #Inject private AnotherBean bean; (or #Autowired) (preferred)
get ahold of the ApplicationContext (for ex. implement ApplicationContextAware) and call .getBean(..)
Java:
class MyBean {
#Autowired
private OtherBean theBeanYouWantToGet;
}
XML:
<beans ...>
<context:annotation-config/>
<import resource="the-other-xml-file-that-you-can't-touch.xml"/>
<bean class="...MyBean"/>
</beans>