У меня есть приложение, использующее встроенный Jetty 9.2.6 с аннотированными асинхронными сервлетами (и я использую Facelets для создавать шаблоны интерфейса). Существует случайное исключение, которое возникает, когда я обращаюсь к любому сервлету с asyncSupported = true
.Embedded Jetty 9 с асинхронными сервлетами генерирует NullPointerException в org.eclipse.jetty.server.Request.extractFormParameters (Request.java:326)
Вот один трассировки стека случайного исключения:
09:31:42.801 [qtp1262773598-20] DEBUG c.d.a.v.c.CitiesPerStateServlet - APPTEST-BUG
java.lang.NullPointerException: null
at org.eclipse.jetty.server.Request.extractFormParameters(Request.java:326) ~[jetty-server-9.2.6.v20141205.jar:9.2.6.v20141205]
at org.eclipse.jetty.server.Request.extractContentParameters(Request.java:302) ~[jetty-server-9.2.6.v20141205.jar:9.2.6.v20141205]
at org.eclipse.jetty.server.Request.extractParameters(Request.java:256) ~[jetty-server-9.2.6.v20141205.jar:9.2.6.v20141205]
at org.eclipse.jetty.server.Request.getParameter(Request.java:827) ~[jetty-server-9.2.6.v20141205.jar:9.2.6.v20141205]
at com.doitlabs.app99vendas.view.controller.CitiesPerStateServlet$1.run(CitiesPerStateServlet.java:55) ~[classes/:na]
at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1173) [jetty-server-9.2.6.v20141205.jar:9.2.6.v20141205]
at org.eclipse.jetty.server.AsyncContextState$2.run(AsyncContextState.java:168) [jetty-server-9.2.6.v20141205.jar:9.2.6.v20141205]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:626) [jetty-util-9.2.6.v20141205.jar:9.2.6.v20141205]
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:546) [jetty-util-9.2.6.v20141205.jar:9.2.6.v20141205]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_20]
Вот мой сервлет, на который ссылается в трассировки стека:
@WebServlet(urlPatterns = { "/controllers/cities-per-state" }, asyncSupported = true)
public class CitiesPerStateServlet extends HttpServlet {
final Logger LOGGER = LoggerFactory.getLogger(CitiesPerStateServlet.class);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.processRequest(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.processRequest(req, resp);
}
private void processRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext ac = req.startAsync(req, resp);
ac.start(new Runnable() {
@Override
public void run() {
HttpServletRequest req_ = (HttpServletRequest)ac.getRequest();
try {
String stateId = req_.getParameter("state_id");
Collection<City> cities = null;
if (stateId != null) {
cities = CityDAO.retrieveByState(new Long(stateId));
}
req_.setAttribute("cities", cities);
ac.dispatch("/pages/system-ops/campaign/cities-per-state.xhtml");
} catch (Exception e) {
if (LogUtil.shouldLog(e)) {
LOGGER.debug(BUG, e);
}
}
}
});
}
}
Вот как я начинаю внедренного Jetty:
public class Main {
public static void main(String[] args) throws Exception {
String webappDirLocation = "./src/main/webapp/";
String webPort = System.getenv("PORT");
if (webPort == null || webPort.isEmpty()) {
webPort = "8080";
}
Server server = new Server(Integer.valueOf(webPort));
ClassList classlist = org.eclipse.jetty.webapp.Configuration.ClassList.setServerDefault(server);
classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration");
WebAppContext context = new WebAppContext();
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/classes/.*");
context.setDescriptor(webappDirLocation + "/WEB-INF/web.xml");
context.setBaseResource(new ResourceCollection(new String[] { webappDirLocation, "./target" }));
context.setResourceAlias("/WEB-INF/classes/", "/classes/");
context.setContextPath("/");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
server.join();
}
}
файл web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- Parameters ######################################################## -->
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<!-- Servlet mappings ################################################## -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Listerners ######################################################## -->
<listener>
<listener-class>
com.sun.faces.config.ConfigureListener
</listener-class>
</listener>
<!-- Session config #################################################### -->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<!-- Welcome ########################################################### -->
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Это проект Maven, так вот мой pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.doitlabs.app99vendas</groupId>
<version>1.0-SNAPSHOT</version>
<name>app99vendas.net</name>
<artifactId>99vendas.net</artifactId>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.2.6.v20141205</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<version>9.2.6.v20141205</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.6.v20141205</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.8</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.8</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.3-1102-jdbc41</version>
</dependency>
<dependency>
<groupId>com.mandrillapp.wrapper.lutung</groupId>
<artifactId>lutung</artifactId>
<version>0.0.5</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Кто-нибудь есть ключ, почему это происходит?
Если вам нужна дополнительная информация, то дайте мне знать.
Заранее благодарен!
спасибо, @Joakim Erdfelt. Была деталь, о которой я не знал, потому что многие примеры, которые я видел во многих блогах. Один последний вопрос, внутри асинхронного контекста (т. Е. Метод run), после некоторой обработки, если мне нужно поместить некоторые данные на HttpSession, будет безопасно вызывать ((HttpServletRequest) ac.getRequest()). GetSession(). setAttribute ("SOME_DATA", объект)? – reinaldoluckman