2014-12-20 5 views
0

주석이 달린 비동기 Servlet이있는 임베디드 Jetty 9.2.6을 사용하는 응용 프로그램이 있습니다. (그리고 Facelets를 사용하여 인터페이스 템플릿 만들기). asyncSupported = true으로 서블릿에 액세스 할 때 발생하는 임의의 예외가 있습니다.비동기 Servlet이 포함 된 Embedded Jetty 9가 org.eclipse.jetty.server.Request.extractFormParameters (Request.java:326)에서 NullPointerException을 발생시킵니다.

다음
@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); 
        }      
       }      
      } 
     });  
    } 
} 

내가 내 포함 된 부두를 시작하는 방법은 다음과 같습니다 :

여기
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] 

는 스택 추적에서 참조 내 서블릿입니다 : 여기

는 임의의 예외의 하나의 스택 추적입니다
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 파일

그것은, 그래서 여기에 메이븐 프로젝트 내 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> 

사람이 이런 일이 왜 단서가 있습니까?

자세한 정보가 필요하면 알려주십시오.

미리 감사드립니다. AsyncContext에서 HttpServletRequestHttpServletResponse 객체에

답변

3

액세스 (그들은 스레드로부터 안전하지되며, AsyncContext 수명주기가 완료되기 전에, 심지어 재활용 할 수 있습니다)를 AsyncContext의 외부 액세스와 같은 하지 있습니다. 실제로 대부분의 컨테이너는 AsyncContext이 시작 되 자마자 가비지 수집의 이유로 재활용 할 수 있습니다.

커플이 함께 HttpServletRequest.getParameter(String name) 행동 (이 가능한 모든 매개 변수를 얻을뿐만 아니라 요청 본문 내용을 읽을 필요), 당신은 당신의 코드를 변경해야 어디 상황이있다.

는 당신이 startAsync() 전화하여 AsyncListener.onStartAsync() 또는 Runnable 구현에 그 정보를 전달 전에 HttpServletRequest에서 당신이 할 수있는 읽을 것을 권장된다.

+0

감사합니다. @Joakim Erdfelt. 내가 알지 못했던 세부 사항이었습니다. 많은 블로그에서 본 많은 사례들이 있었기 때문입니다. 하나의 마지막 질문, 비동기 컨텍스트 (즉, 메서드 실행), 일부 처리 후 일부 데이터를 HttpSession에 넣어야하는 경우 ((HttpServletRequest) ac.getRequest()). getSession()을 호출하는 것이 안전합니다. setAttribute ("SOME_DATA", object)? – reinaldoluckman