Possibilities of resolving backing beans in JSF and Spring - spring

I use org.springframework.web.jsf.el.SpringBeanFacesELResolver in my JSF + Spring application. Every backing bean needs an interface to be resolved. I guess that it's interface type of dependency injection.
#{bean.text}
public interface IBean {
String getText();
}
#Named
#Scope("session")
public class Bean implements IBean {
public String getText() {
return "Hello World!";
}
}
I would like to get rid of the interface. It's kind of bureaucracy for me. Is it possible?

I finally solved it. The problem was in beans with scope depending on HTTP (request, session). By default interfaces should be manually created. This can be avoided by using proxies.
If using component scan:
<context:component-scan base-package="..." scoped-proxy="targetClass" />
Or in bean definition:
<bean ...>
<aop:scoped-proxy>
</bean>
See chapter 4.5.4.5 Scoped beans as dependencies in Spring documentation. http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html

Related

what is the usage of new keyword while using java configuration in spring

I have a question around the usage of new keyword being used when using java configuration in spring. What is the need of using new keyword
Refer below mentioned example:
Code implemented using Java Config
#Configuration
public class HelloWorldConfig {
#Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
The above code will be equivalent to the following XML configuration
<beans>
<bean id = "helloWorld" class = "com.test.HelloWorld" />
</beans>
In XML config, we do not use new keyword whereas in java config we are using new keyword. can someone please explain the difference
In the XML configuration, you explain to the system what class should be instanciated (there is a "new" but it is behind the scene) but in the Java Config you actually have to return an instance so that is why we use the 'new' keyword. 'new' simply creates an instance of your class.
The two examples shown in question are not really equivalent.
What the
<beans>
<bean id="helloWorld"
class="com.test.HelloWorld" />
</beans>
really does, is it tells Spring to instantiate class com.test.HelloWorld, and name the resulting bean "helloWorld".
Then the java-config approach is not really doing this. Instead this follows the factory-method pattern, when we tell Spring, that the return value of the method is the bean, and the method name is the name of that bean.
An equivalent of that in XML would be the mentioned factory-method approach, which in this case would look something like this:
<beans>
<bean id="helloWorldConfig"
class="com.test.HelloWorldConfig" />
<bean id="helloWorld"
factory-bean="helloWorldConfig"
factory-method="helloWorld" />
</beans>
Note that there are several approaches to factory-method. In the above, we are assuming, the `helloWorldConfig" is the factory, and we're specifying the method on that bean. Theare are cases with static factory methods too. See here for more examples.
<beans>
<bean id = "helloWorld" class = "com.test.HelloWorld" />
</beans>
This XML configurations tells Spring to "create an instance of com.test.HelloWorld and put it in the bean context with bean id helloWorld".
#Configuration
public class HelloWorldConfig {
#Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
In this Java configuration, we are returning an instance of com.test.HelloWorld. Because of the #Bean annotation, this instance is put into the bean context. As no specific bean id is given, the bean id is derived from the method hellowWorld() and thus becomes helloWorld.
As you can see, both configurations require an instance of com.test.HelloWorld. The XML configuration implicitly creates the instance whereas in the Java configuration you have to explicitly do it yourself.

How can I create the spring bean after all other beans?

For example, I have 3 beans in my spring configuration: A, B, C. And I want to create bean B and C as usual. And than (when all others beans were created) I want to ask spring to create bean A.
Any suggestion ?
Thanks.
Spring framework triggers a ContextRefreshedEvent once the contexts has been fully refreshed and all the configured beans have been created.
You could try to create a listener to catch that event and initialise bean A.
#Component
public class ContextRefreshedEventListener implements
ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// Init your bean here
}
}
You should try #DependsOn adnotation
For example
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
I know it's not really a bean ordering answer, but maybe you can achieve your goal with a #PostConstruct method that will be called just after a bean is constructed, dependencies are injected and all properties are set.
best nas
Easier way to do this would be using #Lazy annotation to your bean. This makes your bean do not get initialized eagerly during context initialization. In simple words,your bean will get created when you ask for it, not before.
#Bean
#Lazy
public A beanA() {
//some code here
}

#PostConstruct spring does not get called without bean declaration

Why post construct does not get called without putting bean in applicationContext.xml
Here is my class which contains #PostConstruct annotation.
package org.stalwartz.config;
import javax.annotation.PostConstruct;
import javax.inject.Singleton;
#Singleton
public class PropertyLoader {
#PostConstruct
public void init() {
System.out.println("PropertyLoader.init()");
}
}
Below is my applicationContext.xml
<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:dwr="http://www.directwebremoting.org/schema/spring-dwr" xmlns:tx="http://www.springframework.org/schema/tx"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr/spring-dwr-3.0.xsd">
<dwr:annotation-config />
<dwr:annotation-scan base-package="org.stalwartz" scanDataTransferObject="true" scanRemoteProxy="true" />
<dwr:url-mapping />
<!-- <bean id="proeprtyLoader" class="org.stalwartz.config.PropertyLoader"></bean> -->
<dwr:controller id="dwrController" debug="false">
<dwr:config-param name="activeReverseAjaxEnabled" value="true" />
</dwr:controller>
<context:annotation-config>
<context:component-scan base-package="org.stalwartz" annotation-config="true"></context:component-scan>
</context:annotation-config>
<mvc:annotation-driven />
...
...
...
</beans>
Looks simple, but it does not work without uncommenting bean declaration.
In Spring environment initialization callback method (the one annotated by #PostConstruct) make sense only on spring-managed-beans. To make instance(s) of your PropertyLoader class managed, you must do one of the following:
Explicitly register your class in context configuration (as you did)
<bean id="proeprtyLoader" class="org.stalwartz.config.PropertyLoader"></bean>
Let component scanning do the work (as you nearly did), but classes must be annotated by one of #Component, #Repository, #Service, #Controller.
Note from Spring documentation: The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. There is usually no need to include the <context:annotation-config> element when using <context:component-scan>.
Because putting bean in applicationContext.xml you are adding bean to Spring container, which has interceptor for this annotation. When Spring inject beans it checks #PostConstruct annotation, between others.
When you call simple new PropertyLoader() JVM will not search for the #PostConstruct annotation.
From doc of #PostConstruct annotation:
The PostConstruct annotation is used on a method that needs to be executed
after dependency injection is done to perform any initialization. This
method MUST be invoked before the class is put into service. This
annotation MUST be supported on all classes that support dependency
injection. The method annotated with PostConstruct MUST be invoked even
if the class does not request any resources to be injected.
Singleton is a scope annotation. It can be used to declare 'singletone' scope for a particular bean, but not instantiate it. See this article.
If you want to instantiate your class as singleton you can try Spring Service annotation.
#Service
public class PropertyLoader {
#PostConstruct
public void init() {
System.out.println("PropertyLoader.init()");
}
}
Also, you can replace annotation-config tag with component-scan. Here is a good article about differences of annotation-config and component-scan tags.
you are using #Singleton from javax.inject package which is not picked up as bean by spring container. Change it to :
package org.stalwartz.config;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
#Component
public class PropertyLoader {
#PostConstruct
public void init() {
System.out.println("PropertyLoader.init()");
}
}
and the spring will auto detect PropertyLoader and will include it in Spring container as bean via the #Component annotation and this bean will be with singleton scope
by default a bean is singleton scoped in Spring, and #PostConstruct is usually used for service beans and service beans must scoped prototype and here because you need multiple objects for that particular class, Spring will provide you singleton instance.
also by doing this spring will attempt multiple times to find this service bean and finally throws below exception:
java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanCreationException
so try like this in annotation way:
package org.stalwartz.config;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component
#Scope("prototype") //you have to make it prototype explicitly
public class PropertyLoader {
#PostConstruct
public void init() {
System.out.println("PropertyLoader.init()");
}
}
Now every thing is good, and work fine for you.
add this dependency to pom.xml
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

Could not instantiate bean class: Specified class is an interface

I know there are threads similar to this issue. Below is my class and I am configuring it in spring.xml file. Actually HumanResourceService is an interface having only one method.
#Endpoint
public class HolidayEndpoint {
#Autowired
private HumanResourceService humanResourceService;
#Autowired
public HolidayEndpoint(HumanResourceService humanResourceService) throws JDOMException {
this.humanResourceService = humanResourceService;
}
}
My problem is that in my spring.xml file, when I define HumanResourceService as bean, it cannot be instantiated as this is an interface. How can I mention an interface in spring configuration file. My spring.xml file is below
<bean id="holidayEndpoint" class="com.mycompany.hr.ws.HolidayEndpoint" autowire="constructor" >
<property name="humanResourceService" ref="humanResourceService" />
</bean>
<bean id="humanResourceService" class="com.mycompany.hr.service.HumanResourceService" />
You can't, Spring needs something it can make an instance from, the interface isn't enough.
In your spring.xml, the value of the class attribute for your bean with id="humanResourceService" should be the name of your implementation class, not the interface. Spring needs you to tell it what implementation class you want it to use for this.

How to use the same bean in two different spring contexts?

I have two spring contexts and I need to use the same bean in both of them. Is there a way to share a bean between two contexts without making a parent context?
I don't think what you want is a good idea. If you have the same bean in two contexts, then which context manages the bean's lifecycle? By having a common parent owning the bean, you have a clear, unambiguous answer to that important question: the bean belongs to the parent context.
Now, if you know the beans will belong to context A and only want to bind them to some name in context B, I guess you could hack some kind of "guest" bean factory or whatever, that does something like:
Java:
public class GuestBeanFactory {
private ApplicationContext guestBeanContext;
#Inject
public void setGuestBeanContext(ApplicationContext guestBeanContext) {
this.guestBeanContext = guestBeanContext;
}
private String guestBeanName;
#Inject
public void setGuestBeanName(String guestBeanName) {
this.guestBeanName = guestBeanName;
}
public Object getBean() {
return guestBeanContext.getBean(guestBeanName);
}
}
applicationContext.xml:
<beans ...>
...
<bean id="myGuestFactory" class="GuestBeanFactory" scope="singleton">
<property name="guestBeanContext" ref="...get a reference to the guest bean and inject it here" />
<property name="guestBeanName" value="name-of-this-bean-inside-guestBeanContext"/>
</bean>
<bean id="myGuestBean" factory-bean="myGuestFactory" factory-method="getBean"/>
...
</beans>
This way, guestBeanContext manages name-of-this-bean-inside-guestBeanContext, but the "host" context can access that bean using the name myGuestBean.

Resources