I'm trying to learn pure Spring and to do that i'm converting my Spring-boot application to spring with pure xml configuration.
My question is how can I obtain session scoped property through xml configuration?
Right now i've got this:
#Autowired
private
ConcurrentHashMap<String,Subscription> subscriptionConcurrentHashMap;
(...)
#Bean
#SessionScope
private ConcurrentHashMap<String, Subscription> getConcurrentHashMap(){
return new ConcurrentHashMap<>();
}
And it works, but i'm not sure how to define generic java class as session scoped bean in xml.
I've found a way to this like that:
<bean name="subscriptionConcurrentHashMapBean" class="java.util.concurrent.ConcurrentHashMap" scope="session">
<aop:scoped-proxy/>
</bean>
and then just reference in controller bean:
<property name="subscriptionConcurrentHashMap" ref="subscriptionConcurrentHashMapBean"/>
Generic type of this hashMap apparently doesn't matter
Related
Currently I use the following method to inject properties into beans:
app.properties:
SingletonBean.valueA=this is a value
spring.xml:
<context:property-placeholder location="classpath:app.properties"/>
<context:component-scan base-package="..."/>
SingletonBean.java:
#Component
public class SingletonBean {
#Value("${SingletonBean.valueA}")
private String valueA;
}
This works great and is extremely convenient to be able to keep all my configs in a single, simple properties file. Is there any way I could extend this to work with multiple Beans of the same class? I need to do the following, with the 2 beans having different properties:
#Autowired private SampleBean beanA;
#Autowired private SampleBean beanB;
I know I can use the #Qualifier(name=...) annotation to support the following xml:
<bean id="beanA" class="SampleBean">
<property name="key1" value="A1"/>
<property name="key2" value="A2"/>
</bean>
<bean id="beanB" class="SampleBean">
<property name="key1" value="B1"/>
<property name="key2" value="B2"/>
</bean>
But with this I am forced to use old style setters in my SampleBean class, where I would prefer to use the newer #Value annotations.
Anyone know of a way to accomplish what I want that remains most consistent with how I am currently injecting my other beans?
The simple solution is just to inject all of the properties into the bean that utilizes the 2 SampleBean instances and create them with new instead. In my real code however there are actually 3 instances, each with 15 or so properties. This is much more cruft and repetition than I would like.
I have a .properties file having 10 key-values pairs say age =10, name=Jon etc. I have configured a bean in spring which has a map as a member variable.
When the bean is loaded by Spring once I call the getBean method, before that the Map should be loaded with the properties from files. How to do that ?
I know this should be done in one of the lifecycle methods like afterPropertiesSet using InitializingBean or init-method configuration. Is there any other better way to do this ?
You can enable annotations in your beans:
<context:annotation-config />
Then you can define method with #PostConstruct annotation. Spring will execute it during bean initialization process:
class MyBean {
private Map<String, String> properties;
#PostConstruct
public void initialize() {
// read properties and initialize map
}
}
Another option is to inject Properties directly into your bean and provide map-like API to access them:
<util:properties id="myProperties" location="classpath:my-props.properties">
<bean id="myBean" class="com.example.MyBean">
<property name="properties" ref="myProperties" />
</bean>
you can use context property-placeholder within XML spring configuration file using ${...} or from java class configuration file using #value.
There is CXF's PolicyBasedWSS4JInInterceptor that creates a singleton instance:
public static final PolicyBasedWSS4JInInterceptor INSTANCE
= new PolicyBasedWSS4JInInterceptor();
Having no Spring skills I'm struggling with how to set its acestor's (AbstractWSS4JInterceptor) properties map via Spring's bean definitions in a cxf.xml file. Basically I want to configure WSS-related properties like "signaturePropFile" in cxf.xml.
Can someone show how to set the property map of PolicyBasedWSS4JInInterceptor.INSTANCE? Thanks!
I would declare a singleton bean:
<bean id="interceptor" class="whatever.your.package.PolicyBasedWSS4JInInterceptor" scope="singleton"/>
And then inject it wherever I need it
<bean id="anotherBean" ...>
<property name="interceptor" ref="interceptor"/>
</bean>
This other bean would have a normal PolicyBasedWSS4JInInterceptor property like this:
private PolicyBasedWSS4JInInterceptor interceptor;
public PolicyBasedWSS4JInInterceptor getInterceptor() {
return interceptor;
}
public void setPolicyBasedWSS4JInInterceptor(PolicyBasedWSS4JInInterceptor interceptor) {
this.interceptor = interceptor;
}
And you would get the same as declaring it static, expressed in Spring terms. It's up to you which way you prefer, just remember that doing this the Spring way you have your interceptor inside your IoC container, and thus you can instrument it if necessary, etc.
The "action"-based WS-Security properties such as "signaturePropFile" do not work with the WS-SecurityPolicy based interceptors in CXF. CXF has separate configuration tags that you can just pass as JAX-WS properties when using WS-SecurityPolicy, and so you don't need to access any properties of the INSTANCE class. See here for more information:
http://cxf.apache.org/docs/ws-securitypolicy.html
Colm.
I need to inject a object of a java class in spring controller through applicaionContext.xml. My controller will be ,
#Controller
public class SpringController{
private MyClass obj;
}
I know I can do it with #Autowired annotation.
Is this really good to create a object for a controller through applicaionContext.xml ? Also can I inject a object of a class in controller using the <property> tag inside a <bean> tag ?
Is this really possible ? or please forgive me if it is a stupid question.
I need to know the possible ways for how to inject a object of a class in Spring controller ?
You can of course use #Autowired annotation to autowire the relationships, which can reduce the need to define the properties and constructor arguments for the controller in your applicationContext.xml file. And also to add a dependency to a class, you don't need to modify the configuration files.
But it has some disadvantages too, like if you use #Autowired, there will not be any explicit documentation for the wiring details between Spring managed beans. And to know the relationships between the beans, you have to go through your managed beans. But, if you use configuration files to define the relationships, the relationship details can be found in one place.
You can inject an object of a class into your controller through your applicaionContext.xml as below:
Constructor based injection:
#Controller
public class SpringController{
private MyClass obj;
public SpringController(MyClass obj){
this.obj=obj;
}
}
<bean id="myClassImpl" class="x.y.z.MyClassImpl"></bean>
<bean id="springController" class="x.y.z.web.controllers.SpringController">
<constructor-arg ref="myClassImpl"></constructor-arg>
</bean>
Setter based injection:
#Controller
public class SpringController{
private MyClass obj;
public void setObj(MyClass obj){
this.obj=obj;
}
public MyClass getObj(){
return obj;
}
}
<bean id="myClassImpl" class="x.y.z.MyClassImpl"></bean>
<bean id="springController" class="x.y.z.web.controllers.SpringController">
<property name="obj" ref="myClassImpl"></property>
</bean>
If you want to inject an object in a controller and you particularly want to you use xml,then instead of component scanning of Controller you should create a bean of the controller class of singleton scope in the application context.
Your controller class need not be annotated with #Controller.
you then have to you extend some Controller also like AbstractCommandController, AbstractController, AbstractFormController, AbstractWizardFormController, BaseCommandController, CancellableFormController, MultiActionController SimpleFormController, UrlFilenameViewController
Now to inject a particular object you can use Either Constructor and Setter based injection.
or you can use Autowring by name or type to auto inject the object.
Make sure that you have also declared the bean of that object also in Application Context.
After a DispatcherServlet has received a request and has done its work to resolve locales, themes and suchlike, it then tries to resolve a Controller, using a HandlerMapping. When a Controller has been found to handle the request, the handleRequest method of the located Controller will be invoked; the located Controller is then responsible for handling the actual request and - if applicable - returning an appropriate ModelAndView.
Thats it.
Actually, injection with xml and annotation is same behind the scene. Xml is old fashion while annotations are newer.
Basically, there are 2 types of injection types.
byName
Autowiring by property name. Spring container looks at the properties
of the beans on which autowire attribute is set to byName in the XML
configuration file. It then tries to match and wire its properties
with the beans defined by the same names in the configuration file.
You can give explicit names to beans both with xml and annotation.
#Service("BeanName")
#Component("BeanName")
#Controller("BeanName")
<bean name="BeanName" class="someclass"></bean>
and inject beans by using #Qualifier annotation.
#Autowired
#Qualifier("BeanName")
and with xml
<bean id="MyBean2" class="MyBean2 class">
<property name="Property of MyBean2 which refers to injecting bean" ref="BeanName" />
</bean>
byType
Autowiring by property datatype. Spring container looks at the
properties of the beans on which autowire attribute is set to byType
in the XML configuration file. It then tries to match and wire a
property if its type matches with exactly one of the beans name in
configuration file. If more than one such beans exists, a fatal
exception is thrown.
Default auto wiring mode is byType, so spring will look for matching type in auto wiring. However, older versions of Spring has default behavior none on injection. If you want to inject byType using xml, you should tell spring contaioner explicitly.
For example MyBean2 has a reference to MyBean, by setting autowired attribute to byType it handles injection automatically.
<bean id="MyBean" class="MyBean class">
<property name="Property of MyBean2 which refers to injecting bean" ref="BeanName" />
</bean>
<bean id="MyBean2" class="MyBean2 class"
autowire="byType">
</bean>
It also depends on where the injection take place in your code. There are 2 types, setter getter injection and constructor injection.
Note : There is no difference in #Controller since they are already in spring context.
See also
Spring Beans Auto wiring
I ran into such problem. I was getting "Ambiguous mapping found". (I use xml configuration as well and i am injecting a bean into my controller)
Then looking at my console i realized that my controller was being instantiated twice.
In more detailed look i noticed that my annotation
#Controller(value = "aController")
(Note value = "aController")
was different from my xml configuration where i was instatiating the same controller with different bean id
<bean id="aControleRRRRR" class="package.ControllerClassName"
p:property-ref="beanToInject" />
(Note id="aControleRRRRR")
So in conclusion your #Controller name (value = "aController") needs to be exactly the same as the name you give in the XML configuration (id="aControleRRRRR"), so that Spring can manage to distinct that they refer to the same bean (instance)
Hope this helps
I am having difficulty understanding why something in Spring Java Config using #Autowired does not work.
First, I am trying to move all my #Autowired annotations in the Java Config classes. This has the effect of making my "POJOs" back into real POJOs. I can then not only test them easily outside of a Spring context, but can also use mock objects easily and readily.
So I first tried this:
#Configuration
public class Module3ConfigClass {
#Autowired
private Module1Bean1 module1Bean1;
#Autowired
private Module2Bean1 module2Bean1;
#Bean
public Module3Bean1 module3Bean1() {
return new Module3Bean1(module1Bean1, module2Bean1);
}
}
However, when the Module3Bean1 constructor is invoked, both passed in Beans are null. If you didn't follow my made up naming convention above, both of those beans would be created by a separate Java Config configuration file. Also note that everything is wired up correctly - I know this because everything works perfectly when the #Autowired tags are on the corresponding private member fields inside of Module3Bean1.
FWIW, I tried adding an #DependsOn annotation to module3Bean1() method, but had the same results. I guess I just would really like to understand this behavior, is it correct (I suspect it is, but why)?
Finally, I found an acceptable workaround shown here:
#Configuration
public class Module3ConfigClass {
#Bean
#Autowired
public Module3Bean1 module3Bean1(Module1Bean1 module1Bean1, Module2Bean1 module2Bean1) {
return new Module3Bean1(module1Bean1, module2Bean1);
}
}
This seems fine to me, but if anyone would care to comment on it, that would be welcome as well.
I think you came across same problem I just had. In my case problem was invalid xml configuration. In my module B I had config like :
<beans>
<context:component-scan base-package="com.moduleB"/>
<import resource="classpath:applicationContext-moduleA.xml"/>
</beans>
In moduleA context I placed "context:annotation-config" annotation.
When I change import/context order to :
<beans>
<import resource="classpath:applicationContext-moduleA.xml"/>
<context:component-scan base-package="com.moduleB"/>
</beans>
Autowiring for configuration class properties started to work.
We had the same issue and came to the conclusion that the error arose because we had a circular dependency where a BeanPostProcessor was involved.
A PropertyPlaceholderConfigurer (a BeanPostProcessor) has been configured to set its propertiesArray property with the help of another bean:
<bean id="globalPropertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
lazy-init="false" depends-on="javaLoggingConfigurer">
<property name="locations">
<list>
<value>classpath:config/host/${env.instance}.properties</value>
<value>WEB-INF/config/host/${env.instance}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
<property name="propertiesArray" value="#{springPropertyFinder.findProperties()}" />
</bean>
The used springPropertyFinder bean to set the propertiesArray is not a BeanPostProcessor but a "normal" bean that gathers all Properties instances with:
public Properties[] findProperties() {
Map<String, Properties> propertiesMap = applicationContext.getBeansOfType(Properties.class);
for (String title : propertiesMap.keySet()) {
PropertiesLoggerUtil.logPropertiesContent(logger, "Springcontext Properties ("+title+")", propertiesMap.get(title));
}
return propertiesMap.values().toArray(new Properties[propertiesMap.size()]);
}
The #Configuration class contained a bean of type Properties
So our assumption is that the #Configuration class has been created without being processed by the ConfigurationClassPostProcessor (also a BeanPostProcessor), because the PropertyPlaceholderConfigurer depends on the springPropertyFinder, which depends on the properties bean in the #Configuration class. The order of the BeanPostProcessors is probably not setup right under these circumstances.
This described setup worked in XML, but not with Java config.