I have a little problem in integrating spring with JSF.
I understood that either Spring and JSF have distinct containers. So I can't mix their annotations because registered beans will not be visible to each other.
However, I've read an article : Spring DAO is not injected in JSF managed bean where guy says that It's possible to annotate everything with spring annotations make visible these components to JSF.
I'm really confused with xml configuration because sometimes I read that I don't need it but in most cases I see people usually do this.
My question is what need to be configured if I have this source code and I want to make visible spring beans to JSF :
package pl.catarina.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import pl.catarina.domain.Patient;
import pl.catarina.repository.PatientRepository;
import javax.annotation.PostConstruct;
#Component
#Scope("request")
public class RegisterController {
#Autowired
private PatientRepository patientRepository;
private Patient patient;
#PostConstruct
public void init(){
patient = new Patient();
patient.setName("jan");
patient.setSurname("Way");
patient.setPhoneNumber("21421131");
patient.setEmail("asdpad#gmail.com");
patient.setPassword("pdsad223Sdsd");
}
public void save(){
patientRepository.save(patient);
}
}
REPOSITORY
package pl.catarina.repository;
import org.springframework.stereotype.Repository;
import pl.catarina.domain.Patient;
#Repository
public interface PatientRepository extends UserBaseRepository<Patient> {
Patient findByEmail(String email);
}
web.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns = "http://java.sun.com/xml/ns/javaee"
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_2_5.xsd"
id = "WebApp_ID" version="2.5">
<welcome-file-list>
<welcome-file>pages/home.xhtml</welcome-file>
</welcome-file-list>
<!--
FacesServlet is main servlet responsible to handle all request.
It acts as central controller.
This servlet initializes the JSF components before the JSP is displayed.
-->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>com.ocpsoft.pretty.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>bootstrap</param-value>
</context-param>
</web-app>
Related
I want add support to JavaServer Faces to a spring project mine, but the tutorials I found on the web teach that for setting this to a project, add this line to the file web.xml:
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<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>
but my spring project don't use XML files for configuration, only java classes. Anyone can tell me how to configure JavaServer Faces in this scenario?
Equivalent class based configuration would be:
public class MyInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
ServletRegistration.Dynamic facesServlet = servletContext.addServlet("Faces Servlet", new FacesServlet());
facesServlet.setLoadOnStartup(1);
facesServlet.addMapping("/faces/*");
}
}
More details here
I'm injecting two beans inside my backing bean with ManagedProperty. The backing bean is view scope and the model bean is request scope that looks like this:
#ManagedBean(name = "categoryBB")
#ViewScoped
public class CategoryBackingBean implements Serializable {
private static final long serialVersionUID = -880184144170934066L;
private static final Logger LOG = Logger
.getLogger(CategoryBackingBean.class);
#ManagedProperty("#{categoryService}")
CategoryService categoryService;
#ManagedProperty("#{categoryBean}")
CategoryBean categoryBean;
//Getters/Setters...
}
However I'm receiving the following error:
javax.servlet.ServletException: Unable to create managed bean categoryBB.
The following problems were found:
The scope of the object referenced by expression #{categoryBean}, request, is shorter than the referring managed beans (categoryBB) scope of view
javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
My web.xml
<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>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-security.xml
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<!-- Enable Spring-Security TagLib in JSF -->
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
Any suggestion?
I'm getting the java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory. when I deploy my webapp as a .war. Does anyone have an idea where to begin looking for the root cause of this problem? The application runs as expected in the Eclipse IDE, but when exported as a war for deploying on the publicly available stand-alone TomEE environment, it fails.
Many thanks.
My configuration:
Apache TomEE - WebProfile 1.6.0.2
JSF 2.2.7 (com.sun.faces)(Mojarra lib 2.2.0) <-- This may be a problem? But why does the app run in the Eclipse environment but not the stand-alone TomEE?
Maven 4.0.0
java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory.
javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:1004)
javax.faces.FactoryFinder.getFactory(FactoryFinder.java:316)
javax.faces.webapp.FacesServlet.init(FacesServlet.java:302)
org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:744)
The web.xml:
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<display-name>ProjName</display-name>
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.forceLoadConfiguration</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
The jars that are exported in the .war WEB-INF/lib directory:
WEB-INF/lib/javax.faces.jar
WEB-INF/lib/javax.faces-api-2.2.jar
WEB-INF/lib/jsf-api-2.2.7.jar
WEB-INF/lib/jsf-impl-2.2.7.jar
WEB-INF/lib/poi-3.10-FINAL.jar
WEB-INF/lib/commons-codec-1.5.jar
WEB-INF/lib/poi-ooxml-3.10-FINAL.jar
WEB-INF/lib/poi-ooxml-schemas-3.10-FINAL.jar
WEB-INF/lib/xmlbeans-2.3.0.jar
WEB-INF/lib/stax-api-1.0.1.jar
WEB-INF/lib/dom4j-1.6.1.jar
WEB-INF/lib/xml-apis-1.0.b2.jar
WEB-INF/lib/cxf-bundle-jaxrs-2.7.11.jar
WEB-INF/lib/woodstox-core-asl-4.2.1.jar
WEB-INF/lib/stax2-api-3.1.4.jar
WEB-INF/lib/xmlschema-core-2.1.0.jar
WEB-INF/lib/geronimo-javamail_1.4_spec-1.7.1.jar
WEB-INF/lib/wsdl4j-1.6.3.jar
WEB-INF/lib/jaxb-impl-2.1.13.jar
WEB-INF/lib/jetty-server-8.1.14.v20131031.jar
WEB-INF/lib/jetty-continuation-8.1.14.v20131031.jar
WEB-INF/lib/jetty-http-8.1.14.v20131031.jar
WEB-INF/lib/jetty-io-8.1.14.v20131031.jar
WEB-INF/lib/jetty-util-8.1.14.v20131031.jar
WEB-INF/lib/jetty-security-8.1.14.v20131031.jar
WEB-INF/lib/slf4j-api-1.7.6.jar
WEB-INF/lib/geronimo-servlet_3.0_spec-1.0.jar
WEB-INF/lib/javax.ws.rs-api-2.0-m10.jar
WEB-INF/lib/postgresql-9.3-1101-jdbc41.jar
WEB-INF/lib/commons-httpclient-3.1.jar
WEB-INF/lib/commons-logging-1.0.4.jar
WEB-INF/lib/hamcrest-all-1.3.jar
WEB-INF/lib/junit-4.11.jar
WEB-INF/lib/hamcrest-core-1.3.jar
WEB-INF/lib/httpclient-4.3.3.jar
WEB-INF/lib/httpcore-4.3.2.jar
WEB-INF/lib/commons-dbcp2-2.0.jar
WEB-INF/lib/commons-pool2-2.2.jar
WEB-INF/lib/mockito-core-1.9.5.jar
WEB-INF/lib/objenesis-1.0.jar
I resolved this by removing the parameter from the web.xml file.
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
Removing the above text, rebuilding, exporting the war from Eclipse and deploying with the Tomcat Web Application Manager UI resolved the problem. Apparently, one of the jsf jars has this code built-in since http://java.sun.com/xml/ns/javaee/web-app_3_0 . I don't know this to be a fact, but read it in could not find Factory: javax.faces.context.FacesContextFactory. The difference here being that I removed the parameter instead of adding it.
I resolved this issue by removing the web.xml file and put these two methods in the Spring configuration file.
#Bean
public ServletContextInitializer servletContextCustomizer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext sc) throws ServletException {
sc.setInitParameter(Constants.ContextParams.THEME, "bootstrap");
sc.setInitParameter(Constants.ContextParams.FONT_AWESOME, "true");
sc.setInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME,ProjectStage.Development.name());
sc.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");
sc.setInitParameter("contextConfigLocation", "test");
}
};
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean registration = new ServletRegistrationBean(servlet, "*.jsf");
registration.setName("Faces Servlet");
registration.addUrlMappings("*.jsf");
registration.setMultipartConfig(new MultipartConfigElement((String) null));
registration.setEnabled(true);
registration.setLoadOnStartup(1);
return registration;
}
I've read the docs ( http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework ) several times and I can't confirm if the WebApplicationContext context that gets injected when you use the #WebApplicationContext annotation is actually looking at the web.xml.
In other words, I want to test my web.xml configuration. The filters and servlet path specifically. But when I configure my test it ignores the web.xml. (e.g. I try a get request on a URL like this /myServletPath/foo and it fails with a 404.)
My test:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({
"classpath*:WEB-INF/config/application-context.xml",
"classpath*:WEB-INF/oms-servlet.xml",
"classpath*:persistence-context.xml"
})
public class OrderSummaryControllerIntegrationTests {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = webAppContextSetup(this.wac).build();
}
#Test
public void testFindOrderSummariesExpectsSuccess() throws Exception {
mockMvc.perform(get("/oms/orders?user=1234&catalog=bcs"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
}
And my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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-app_2_5.xsd"
version="2.5">
<display-name>OMS REST Services</display-name>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<filter>
<filter-name>webappMetricsFilter</filter-name>
<filter-class>com.yammer.metrics.web.DefaultWebappMetricsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>webappMetricsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/application-context.xml, classpath*:persistence-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>oms</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>oms</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
You are right, Spring-mvc-test does not read the web.xml file, but you can configure the filters this way:
webAppContextSetup(this.wac).addFilter(new DefaultWebappMetricsFilter(), "/*").build()
I'm attempting to make use of JAX-RS' (Jersey) MVC pattern. Attempts to reach http://localhost:8080/myproject/foos/test result in an error that reads:
java.io.IOException: The template name, /view, could not be resolved to a fully qualified template name
http://localhost:8080/myproject/foos results in the same error.
What am I missing?
Resource:
package resources;
import com.sun.jersey.api.view.Viewable;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("foos")
public class FooResource {
#GET
#Produces(MediaType.TEXT_HTML)
public Viewable get() {
return new Viewable("/index", this);
}
#GET
#Path("{id}")
#Produces(MediaType.TEXT_HTML)
public Viewable get(#PathParam("id") String id) {
return new Viewable("/view", id);
}
}
Views:
WEB-INF / jsp / resources / FooResource
index.jsp
view.jsp
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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-app_3_0.xsd">
<filter>
<filter-name>jersey</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/(resources|images|js|styles|(WEB-INF/jsp))/.*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<description>Set the default, base template path to the WEB-INF folder.</description>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Made the following changes:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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-app_3_0.xsd">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>welcome.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>jersey</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>controllers</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/((WEB-INF/views))/.*</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/views/</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.feature.Redirect</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.feature.FilterForwardOn404</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Resource:
#Path("foos")
public class FooResource {
#GET
#Produces(MediaType.TEXT_HTML)
public Viewable index() {
return new Viewable("/foos/index", this);
}
#GET
#Path("{id}")
#Produces(MediaType.TEXT_HTML)
public Viewable view(#PathParam("id") String id) {
return new Viewable("/foos/view", id);
}
}
Views:
\welcome.jsp
\WEB-INF\views\foos\
index.jsp
view.jsp
I had this same error running under Jetty 9. The application ran fine using mvn clean jetty:run but had this error when packaged as a war and deployed under Jetty. This is the fix in web.xml that worked for me:
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
- <param-value>/WEB-INF/views/</param-value>
+ <param-value>/WEB-INF/views</param-value>
</init-param>
Yep, that's it. So, hopefully this helps someone who stumbles across this. My config is basically the same as craig's, but had the extra slash.
From initial inspection I think you want to put index.jsp and view.jsp directly in WEB-INF/jsp.
The name should be a fully qualified name like /index.jsp or /index.html.