Why is <context: component-scan> not resolving Spring beans in OSGi Fragment package?
I am creating a Spring 3 application, JSF 2, OSGi (Virgo Tomcat 3.5.0.M03).
I currently have a host web and a set of fragments. The snippets package adds some .xhtml
JSF nodes (facelets) to the host. JSF pages in a fragment have their own UI controllers (Spring beans associated with a commandButton using the action attribute).
I have configured Spring beans with <context:component-scan base-package="my.scan.package" />
in a host (web application) package applicationContext.xml
.
Now, while it context:component-scan
works for the host (i.e. Spring beans acting as UI controllers), it doesn't work for the fragment:
javax.el.PropertyNotFoundException: /flow-deployer-db.xhtml @20,50 action="#{uiControllerDb.deployFlow()}": Target Unreachable, identifier 'uiControllerDb' resolved to null
com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:107)
So while the snippet has to be part of the same class as its host and the ui controller class is declared in that snippet as such:
package my.scan.package;
...
@Component("uiControllerDb")
public class UIControllerDb implements Serializable {
It cannot resolve the bean in the fragment (while running on the node node):
<h:commandButton id="deployFlow" value="Deploy Flow" type="submit"
action="#{uiControllerDb.deployFlow()}" />
Extract from package hosts MANIFEST.MF
...
Bundle-SymbolicName: web.host
Bundle-Version: 4.0.0.alpha
Require-Bundle: org.glassfish.com.sun.faces
Import-Package: javax.naming,javax.sql
Import-Bundle: org.eclipse.virgo.web.dm;version="[3.0.2.RELEASE,4)"
Import-Library: org.springframework.spring;version="[3.0,3.1.1)"
Bundle-Name: Web Host bundle
Web-ContextPath: /webHost
Excerpt from snippet MANIFEST.MF:
Bundle-SymbolicName: my.fragment.bundle
Bundle-Version: 4.0.0.alpha
Import-Library: org.springframework.spring;version="[3.0,3.1.1)"
Fragment-Host: web.host;bundle-version=4.0.0.alpha
How do I get JSF to resolve Spring beans in a fragment? Any pointers are appreciated. Thank.
person-config.xml:
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>contextClass</param-name>
<param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
source to share
Ok I found the answer. Spring context is created when application starts - so adding a fragment with Spring beans does not automatically update the context. Bouncing the container (Virgo) seems to solve the problem - the annotated beans in the fragment become part of the single context of the host fragment.
Thing is, I expected this to happen when the fragment is deployed, since Virgo will update (stop and restart) the node node anyway when the fragment is deployed.
source to share