I've configured my project to load at this URL:
http://localhost:7101/foo/rs/user/home
However, when I deploy the application through JDeveloper I can see this in the Debugging: IntegratedWebLogicServer tab within the IDE:
Target Application WADL -- http://localhost:7101/foo/application.wadl
Target URL -- http://localhost:7101/foo/user/home
Note the /rs part is missing. It's mostly cosmetic (the site loads correctly in the browser when you use the correct URL) but, apart from confusing, it might be a symptom of some configuration issue. Where does JDeveloper get this URL from?
These are some of the hopefully relevant settings:
\ViewController\ViewController.jpr
<hash n="oracle.jdeveloper.model.J2eeSettings">
<value n="j2eeWebAppName" v="Foo-ViewController-webapp"/>
<value n="j2eeWebContextRoot" v="foo"/>
</hash>
ViewController\public_html\WEB-INF\web.xml
<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app 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" xmlns="http://java.sun.com/xml/ns/javaee">
<filter>
<filter-name>JpsFilter</filter-name>
<filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
<init-param>
<param-name>enable.anonymous</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>JpsFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example.foo.view.rest</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature, org.glassfish.jersey.server.mvc.jsp.JspMvcFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>js</extension>
<mime-type>application/javascript</mime-type>
</mime-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Jersey resources</web-resource-name>
<url-pattern>/rs/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>valid-users</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>valid-users</role-name>
</security-role>
<ejb-local-ref>
<ejb-ref-name>ejb/FooEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.example.foo.model.FooEJB</local>
<ejb-link>FooEJB</ejb-link>
</ejb-local-ref>
<listener>
<listener-class>com.example.foo.view.listeners.SessionListener</listener-class>
</listener>
</web-app>
com.example.foo.view.rest.UserService
package com.example.foo.view.rest;
import org.glassfish.jersey.server.mvc.Viewable;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.security.RolesAllowed;
import javax.naming.NamingException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("user")
#RolesAllowed("valid-users")
public class UserService extends BaseService {
public UserService() throws NamingException {
super();
}
#GET
#Path("/home")
#Produces(MediaType.TEXT_HTML)
public Response showHome() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("title", "Home");
return Response.ok(new Viewable("/user/home", map)).build();
}
}
com.example.foo.view.rest.BaseService
package com.example.foo.view.rest;
import com.example.foo.commons.Constants;
import com.example.foo.model.FooEJB;
import javax.annotation.Resource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
public class BaseService {
#Resource
protected FooEJB fooEJB;
#Context
protected HttpServletRequest request;
#Context
protected HttpServletResponse response;
#Context
protected SecurityContext securityContext;
public BaseService() throws NamingException {
InitialContext context = new InitialContext();
fooEJB = (FooEJB)context.lookup(Constants.EJB_JDNI_NAME);
}
}
Related
<web-app>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>de.mycompany.dept.restapi</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/v2/*</url-pattern>
</servlet-mapping>
</web-app>
Even though I declare my url to be /api/v2/* it is still possible to connect to all endpoints without this prefix . This is really annoying. So for example endpoint /employee can be connected
as I wrote in web.xml /api/v2/employee
/employee
I do not want second option. How can I prevent it. Thanks
Maybe Different approach will work. Go to Servlet class and add "import javax.servlet.annotation.WebServlet;". Enter your url path using "#WebServlet" annotation on the class. I leave an example below.
package net.usermanagement.web;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;// Look here
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("foo/baz") // Look here
public class UserServlet extends HttpServlet {
.
.
.
I am trying to show the Alien Object in XML format with AlienResouces as Resource.However, it is giving me 404 error during runtime on the browser and the debugging stmnt GeAlien called is not showing on Tomcat console
Web Service
package com.dip.testproj;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Alien {
private String name;
private int points;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
}
The following is the Resource for the Alien object. The object Alien is getting the resource Name and Number and trying to display it on the browser during runtime.
We Service Resources
package com.dip.testproj
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("aliens")
public class AlienResources {
#GET
#Produces(MediaType.APPLICATION_XML)
public Alien getAlien(){
System.out.println("getAlien Called");
Alien a1 = new Alien();
a1.setName("Navin");
a1.setPoints(60);
return a1;
}
}
There is no compilation error or any error on the console for Tomcat. server. However, it is giving "404" or "Resource could not be found" while trying to run the THIS on the FF browser
The URL Pattern on WEB.xml looks like this.
WEB.XML
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" 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">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.dip.testproj</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>
This is my class:
package pkg.rest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
#Path("/file")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "d://uploaded/"
+ fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
this is my Html File for uploading :
<html>
<body>
<h1>File Upload with Jersey</h1>
<form action="rest/file/upload" method="post" enctype="multipart/form-data">
<p>
Select a file : <input type="file" name="file" size="45" />
</p>
<input type="submit" value="Upload It" />
</form>
</body>
</html>
Web.xml file:
<?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_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>REST_WS</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
when i try to upload file to server then no action perform i dint create client direct run it html file in tomcat server and try to access it please help me what we need to do change this i am writing first time so please help .
You didn't put enough stuff in web.xml, so the container does not know how to route request to your Jersey servlet.
Add the following to your web.xml:
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>pkg.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
You need to have the pattern /rest/* in all the url's which you want to be handled as a service.
I am using JBoss AS 7.1.1, RestEasy 2.3.5.Final, Swagger 1.2.0, Spring 3.1.1
Here is my web.xml,
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/spring/application-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>Bootstrap</servlet-name>
<servlet-class>com.js.api.Bootstrap</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<init-param>
<param-name>swagger.config.reader</param-name>
<param-value>com.js.api.RestEasyConfigReader</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8080/js</param-value>
</init-param>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring application-context & servlet-context.xml are fine and my REST services are wired up and working. But only swagger is not working. Here is ApiListingResource,
package com.js.resource;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.stereotype.Controller;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.jaxrs.listing.ApiListing;
#Path("/api-docs")
#Api("/api-docs")
#Produces({ "application/json" })
#Controller
public class ApiListingResource extends ApiListing {
}
I checked and #Context injection is not working in RestEasy 2.3.5. Anyway created a custom config reader,
import javax.servlet.ServletConfig;
import com.wordnik.swagger.jaxrs.ConfigReader;
public class RestEasyConfigReader extends ConfigReader {
private ServletConfig config;
public RestEasyConfigReader(ServletConfig config){
this.config = config;
}
#Override
public String basePath() {
return getParameterOrDefault("swagger.api.basepath", "http://localhost:8080/js");
}
#Override
public String swaggerVersion() {
return "1.2";
}
#Override
public String apiVersion() {
return "1.0";
}
#Override
public String modelPackages() {
return "com.js.model";
}
#Override
public String apiFilterClassName() {
return null;
}
private String getParameterOrDefault(String key, String defaultValue){
if ((config != null) && (config.getInitParameter(key) !=null ))
return config.getInitParameter(key);
return defaultValue;
}
}
I am always getting NPE error when I try to access http://localhost:8080/js/api-docs
java.lang.NullPointerException
com.wordnik.swagger.jaxrs.ConfigReaderFactory$.getConfigReader(Help.scala:88)
com.wordnik.swagger.jaxrs.listing.ApiListing.resourceListing(ApiListing.scala:64)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:155)
org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:257)
org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:222)
org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:211)
org.jboss.resteasy.springmvc.ResteasyHandlerAdapter.createModelAndView(ResteasyHandlerAdapter.java:87)
org.jboss.resteasy.springmvc.ResteasyHandlerAdapter.handle(ResteasyHandlerAdapter.java:74)
org.jboss.resteasy.springmvc.ResteasyHandlerAdapter.handle(ResteasyHandlerAdapter.java:24)
org.jboss.resteasy.springmvc.ResteasyWebHandlerTemplate.handle(ResteasyWebHandlerTemplate.java:39)
org.jboss.resteasy.springmvc.ResteasyHandlerAdapter.handle(ResteasyHandlerAdapter.java:45)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
Not only the #Context injection is working. Swagger relies on Application & ServletConfig, which is not injected by Spring in method parameters.
I decided its better to write code to fix this.
Configuration is read by a Spring bean. It can be configured in spring xml.
Written a REST resource to expose Documentation.
The REST classes are found by scanning all classes. Used the solution from How do I read all classes from a Java package in the classpath?.
API document for a class is formed by calling Swagger-Jaxrs code
JaxrsApiReader.read(clazz, apiVersion, swaggerVersion, basePath, apiPath)
I am able to wire up swagger 1.3.0, resteasy, spring 3.x and jboss-as-7.
You can configure swagger related beans in spring.xml as follows:
<!-- Swagger providers -->
<bean id="apiDeclarationProvider" class="com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider" />
<bean id="resourceListingProvider" class="com.wordnik.swagger.jaxrs.listing.ResourceListingProvider" />
<!-- Swagger API listing resource -->
<bean id="swaggerResourceJSON" class="com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON" />
<!-- this scans the classes for resources -->
<bean id="swaggerConfig" class="com.wordnik.swagger.jaxrs.config.BeanConfig">
<property name="resourcePackage" value="package.name"/>
<property name="version" value="1.0.0"/>
<property name="basePath" value="http://localhost:8081/resteasy-spring"/>
<property name="title" value="Petstore sample app"/>
<property name="description" value="This is a app."/>
<property name="contact" value="apiteam#wordnik.com"/>
<property name="license" value="Apache 2.0 License"/>
<property name="licenseUrl" value="http://www.apache.org/licenses/LICENSE-2.0.html"/>
<property name="scan" value="true"/>
</bean>
Then You can configure swagger in web.xml as:
<servlet>
<servlet-name>DefaultJaxrsConfig</servlet-name>
<servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
For more detail: visit here.
Recently, we have shifted our Spring application from tomcat to wildfly(JBoos 8). After that, swagger did not work. Previuosly, we have mentioned everytinh in web.xml and it was working fine on tomcat 7. After changing to wildfly, we have done following changes:
We have removed following from web.xml:
<servlet>
<servlet-name>DefaultJaxrsConfig</servlet-name>
<servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8080/rest/api</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Add following in spring-context.xml:
<!-- Swagger providers -->
<bean id="apiDeclarationProvider"
class="com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider" scope="singleton" />
<bean id="resourceListingProvider"
class="com.wordnik.swagger.jaxrs.listing.ResourceListingProvider" scope="singleton"/>
<!-- Swagger API listing resource -->
<bean id="swaggerResourceJSON"
class="com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON" />
<!-- this scans the classes for resources -->
<bean id="swaggerConfig" class="com.wordnik.swagger.jaxrs.config.BeanConfig">
<property name="resourcePackage" value="com.rest" />
<property name="version" value="1.0.0" />
<property name="basePath" value="https://localhost:9880/rest/api" />
<property name="title" value="REST API" />
<property name="scan" value="true" />
</bean>
NOTE: You need to define scope=singleton otherwise wildfly will throw an exception.
Now, Restart your server, and load your URL. It should work.
I've read #EJB in #ViewScoped managed bean causes java.io.NotSerializableException, but my state saving setting is server.
Here is what I have:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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">
<display-name>sispra</display-name>
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
<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>*.jsf</url-pattern>
</servlet-mapping>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>glass-x</param-value>
</context-param>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure Application</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>fileRealm</realm-name>
</login-config>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>
customer.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>TODO supply a title</title>
</h:head>
<h:body>
<p:growl id="messages"/>
<h:form>
<p:commandButton actionListener="#{customerController.create}" value="save" update="#form :messages"/>
<p:panel>
<f:facet name="header">
<h:outputText value="Details"/>
</f:facet>
<h:panelGrid columns="3">
<h:outputLabel for="name" value="#{bundle['person.name']}"/>
<p:inputText id="name" label="#{bundle['person.name']}" value="#{customerController.selected.name}"/>
<p:message for="name"/>
<h:outputLabel for="surname" value="#{bundle['person.surname']}"/>
<p:inputText id="surname" label="#{bundle['person.surname']}" value="#{customerController.selected.surname}"/>
<p:message for="surname"/>
</h:panelGrid>
</p:panel>
</h:form>
</h:body>
</html>
CustomerController.java:
package it.shape.sispra.controllers;
import it.shape.sispra.ejb.PersonFacade;
import it.shape.sispra.entities.Customer;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class CustomerController extends AbstractController<Customer>
{
private static final long serialVersionUID = 134755304347034L;
#EJB
private PersonFacade facade;
public CustomerController()
{
super(Customer.class);
}
#Override
public PersonFacade getFacade()
{
return facade;
}
}
PersonFacade.java:
package it.shape.sispra.ejb;
import it.shape.sispra.entities.Person;
import javax.ejb.Stateless;
#Stateless
public class PersonFacade extends AbstractFacade<Person>
{
private static final long serialVersionUID = 4357823648345L;
public PersonFacade()
{
super(Person.class);
}
}
AbstractFacade.java:
package it.shape.sispra.ejb;
import it.shape.sispra.entities.AbstractEntity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.queries.QueryByExamplePolicy;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
public abstract class AbstractFacade<T extends AbstractEntity> implements Serializable
{
private static final long serialVersionUID = 12467890452346123L;
#PersistenceContext(unitName = "sispra")
private EntityManager em;
private final Class<T> entityClass;
public AbstractFacade(Class<T> entityClass)
{
this.entityClass = entityClass;
}
public EntityManager getEntityManager()
{
return em;
}
public void create(T entity)
{
getEntityManager().persist(entity);
}
public void edit(T entity)
{
getEntityManager().merge(entity);
}
public void remove(T entity)
{
getEntityManager().remove(getEntityManager().merge(entity));
}
public void refresh(T entity)
{
getEntityManager().refresh(entity);
}
public T find(Object id)
{
return getEntityManager().find(entityClass, id);
}
public List<T> findAll()
{
CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass);
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int first, int max)
{
CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass);
cq.select(cq.from(entityClass));
TypedQuery<T> q = getEntityManager().createQuery(cq);
q.setMaxResults(max);
q.setFirstResult(first);
return q.getResultList();
}
public int count()
{
CriteriaQuery<Long> cq = getEntityManager().getCriteriaBuilder().createQuery(Long.class);
Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
TypedQuery<Long> q = getEntityManager().createQuery(cq);
return q.getSingleResult().intValue();
}
#SuppressWarnings("unchecked")
public T findByExample(T entity)
{
// Create a native EclipseLink query using QBE policy
QueryByExamplePolicy policy = new QueryByExamplePolicy();
policy.addSpecialOperation(String.class, "like");
ReadObjectQuery roq = new ReadObjectQuery(entity, policy);
// Wrap the native query in a standard JPA Query and execute it
Query query = JpaHelper.createQuery(roq, getEntityManager());
return (T) query.getSingleResult();
}
#SuppressWarnings("unchecked")
public List<T> findAllByExample(T entity)
{
// Create a native EclipseLink query using QBE policy
QueryByExamplePolicy policy = new QueryByExamplePolicy();
policy.addSpecialOperation(String.class, "like");
ReadAllQuery raq = new ReadAllQuery(entity, policy);
// Wrap the native query in a standard JPA Query and execute it
Query query = JpaHelper.createQuery(raq, getEntityManager());
return query.getResultList();
}
#SuppressWarnings("unchecked")
public List<T> findByExample(T entity, int start, int max)
{
// Create a native EclipseLink query using QBE policy
QueryByExamplePolicy policy = new QueryByExamplePolicy();
policy.addSpecialOperation(String.class, "like");
ReadAllQuery raq = new ReadAllQuery(entity, policy);
// Wrap the native query in a standard JPA Query and execute it
Query query = JpaHelper.createQuery(raq, getEntityManager());
query.setFirstResult(start);
query.setMaxResults(max);
return query.getResultList();
}
public int countByExample(T entity)
{
//TODO find a better way...
return findAllByExample(entity).size();
}
}
and this is the stacktrace:
GRAVE: Exiting serializeView - Could not serialize state: com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
java.io.NotSerializableException: com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at java.util.HashMap.writeObject(HashMap.java:1001)
at sun.reflect.GeneratedMethodAccessor45.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at java.util.HashMap.writeObject(HashMap.java:1001)
at sun.reflect.GeneratedMethodAccessor45.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1346)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1154)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.apache.myfaces.renderkit.ServerSideStateCacheImpl.serializeView(ServerSideStateCacheImpl.java:357)
at org.apache.myfaces.renderkit.ServerSideStateCacheImpl.saveSerializedViewInServletSession(ServerSideStateCacheImpl.java:220)
at org.apache.myfaces.renderkit.ServerSideStateCacheImpl.saveSerializedView(ServerSideStateCacheImpl.java:798)
at org.apache.myfaces.renderkit.html.HtmlResponseStateManager.saveState(HtmlResponseStateManager.java:127)
at org.apache.myfaces.application.StateManagerImpl.saveView(StateManagerImpl.java:166)
at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1554)
at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:281)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:85)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:239)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:191)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:662)
I know I can workaround this by declaring PersonFacade as transient and use JNDI to get EJB reference after recontruction, but I really dislike this approach.
Is it possible that Glassfish 3.1.1 provides non-serializable EJBs? Is there a way to use #EJB and #ViewScoped together?
update:
i found that this is a MyFaces related issue, all is working fine using mojarra
I have seen the problem too. What I have done in the past is split my bean into a StateBean which is #ViewScoped and an ActionsBean which is #RequestScoped. The ActionBean is injected with the StateBean as well as any EJBs or non-serializable resource accessing objects. On the front-end you use the StateBean for accessing properties and ActionsBean for performing actions.
I would love to hear from someone else who would make my "bean splitting" pattern deprecated.
This is an example of what I do:
#ManagedBean
#ViewScoped
public class CustomControllerStateBean implements Serializable {
private static final long serialVersionUID = 134755304347034L;
private Person selected;
public Person getSelected() {
return selected;
}
public void setSelected(Person selected) {
this.selected = selected;
}
}
Notice CustomControllerStateBean is #ViewScoped and is Serializable an only contains Serializable objects.
#ManagedBean
#RequestScoped
public class CustomControllerActionsBean {
#EJB
private PersonFacade facade;
#Inject
private CustomControllerStateBean state;
public void create() {
facade.create(state.getSelected());
}
}
Notice CustomControllerActionsBean is #RequestScoped and is NOT Serializable an contains non-Serializable objects.
Your front-end will no look like this:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>TODO supply a title</title>
</h:head>
<h:body>
<p:growl id="messages"/>
<h:form>
<p:commandButton actionListener="#{customerControllerActionsBean.create}" value="save" update="#form :messages"/>
<p:panel>
<f:facet name="header">
<h:outputText value="Details"/>
</f:facet>
<h:panelGrid columns="3">
<h:outputLabel for="name" value="#{bundle['person.name']}"/>
<p:inputText id="name" label="#{bundle['person.name']}" value="#{customerControllerStateBean.selected.name}"/>
<p:message for="name"/>
<h:outputLabel for="surname" value="#{bundle['person.surname']}"/>
<p:inputText id="surname" label="#{bundle['person.surname']}" value="#{customerControllerStateBean.selected.surname}"/>
<p:message for="surname"/>
</h:panelGrid>
</p:panel>
</h:form>
</h:body>
</html>
Notice CustomControllerActionsBean is used at the top in the p:commandButton and CustomControllerStateBean is used in the p:inputTexts.
:) I had the same problem: https://issues.apache.org/jira/browse/MYFACES-3581
David Blevins over at the Apache TomEE helped me a log a bug and patch for MyFaces. The problem was generated proxy classes aren't on the classloader path for their deserializer.
A workaround is to set this web-app param to false: org.apache.myfaces.SERIALIZE_STATE_IN_SESSION