2 Replies Latest reply on Jan 6, 2006 2:46 PM by tom.elrod

    Bug in sertvlet remote transport.

    dreyk

      Servlet remote transport doesn't work because ServerInvokerServlet invoke method
      public void processRequest(HttpServletRequest request, HttpServletResponse response) in ServletServerInvokerMBean, and in this
      for get request input stream and response output stream used method
      request.getInputStream() and response.getOutputStream but this method can properly work under servlet container and in you MBean it doesn't work. That's why i reiplement ServerInvokerServlet and ServletServerInvokerMBean

      I chande processRequest(HttpServletRequest request, HttpServletResponse response) method in ServletServerInvokerMBean to the

      byte[] processRequest(HttpServletRequest request,byte[] requestByte, HttpServletResponse response)
       throws ServletException, IOException;
      :
       public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
       {
       Map metadata = new HashMap();
      
      
       Enumeration enumer = request.getHeaderNames();
       while(enumer.hasMoreElements())
       {
       Object obj = enumer.nextElement();
       String headerKey = (String) obj;
       String headerValue = request.getHeader(headerKey);
       metadata.put(headerKey, headerValue);
      
       }
      
       Map urlParams = request.getParameterMap();
      
       metadata.putAll(urlParams);
      
      
       String requestContentType = request.getContentType();
      
      
       try
       {
       Object invocationResponse = null;
      
       ServletInputStream inputStream = request.getInputStream();
      
       UnMarshaller unmarshaller = MarshalFactory.getUnMarshaller(HTTPUnMarshaller.DATATYPE);
       Object obj = unmarshaller.read(inputStream, metadata);
      
       inputStream.close();
       InvocationRequest invocationRequest = null;
      
       if(obj instanceof InvocationRequest)
       {
       invocationRequest = (InvocationRequest) obj;
       }
       else
       {
       if(isBinary(requestContentType))
       {
       invocationRequest = getInvocationRequest(metadata, obj);
       }
       else
       {
       invocationRequest = createNewInvocationRequest(metadata, obj);
       }
       }
      
       try
       {
       // call transport on the subclass, get the result to handback
      
      
      
       invocationResponse = invoke(invocationRequest);
       }
       catch(Throwable ex)
       {
       log.debug("Error thrown calling invoke on server invoker.", ex);
       invocationResponse = null;
       response.sendError(500, "Error processing invocation request. " + ex.getMessage());
       }
      
       if(invocationResponse != null)
       {
       response.setContentType(requestContentType);
       int iContentLength = getContentLength(invocationResponse);
       response.setContentLength(iContentLength);
       ServletOutputStream outputStream = response.getOutputStream();
       Marshaller marshaller = MarshalFactory.getMarshaller(HTTPMarshaller.DATATYPE);
       marshaller.write(invocationResponse, outputStream);
       outputStream.close();
       }
      
       }
       catch(ClassNotFoundException e)
       {
       log.error("Error processing invocation request due to class not being found.", e);
       response.sendError(500, "Error processing invocation request due to class not being found. " + e.getMessage());
      
       }
      
       }


      and change method processRequest in ServerInvokerServlet to the
      protected void processRequest(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException
       {
       boolean trace = log.isTraceEnabled();
       if(trace)
       {
       log.trace("processRequest, ContentLength: " + request.getContentLength());
       log.trace("processRequest, ContentType: " + request.getContentType());
       }
      
       int bufferSize = 1024;
       byte[] byteBuffer = new byte[bufferSize];
       ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
      
       int pointer = 0;
       int contentLength = request.getContentLength();
       ServletInputStream inputStream = request.getInputStream();
       int amtRead = inputStream.read(byteBuffer);
      
       while(amtRead > 0)
       {
       byteOutputStream.write(byteBuffer, pointer, amtRead);
       //pointer+=amtRead;
       if(amtRead < bufferSize && byteOutputStream.size() >= contentLength)
       {
       //done reading, so process
       break;
       }
       amtRead = inputStream.read(byteBuffer);
       }
       byteOutputStream.flush();
       byte[] totalByteArray = byteOutputStream.toByteArray();
      
       byte[] out = servletInvoker.processRequest1(request,totalByteArray, response);
       ServletOutputStream outStream = response.getOutputStream();
       outStream.write(out);
       outStream.flush();
       outStream.close();
       response.setContentLength(totalByteArray.length);
       }


      After this change servlet transport for remote invoking work properly. I think used servlet transport is good idea if you use only HTTP connection to the Jboss server and if you use some load balancer sush is mode_jk.
      Thank tou.

        • 1. Re: Bug in sertvlet remote transport.
          edale

          Looks like you posted the original ServletServerInvoker code instead of the fixed code. I reverse-engineered the fix -- seems to work for me. Here's the missing piece:


           public byte[] processRequest(HttpServletRequest request,byte[] requestByte, HttpServletResponse response) throws ServletException, IOException
           {
           byte[] retval = null;
          
           Map metadata = new HashMap();
          
           Enumeration enumer = request.getHeaderNames();
           while(enumer.hasMoreElements())
           {
           Object obj = enumer.nextElement();
           String headerKey = (String) obj;
           String headerValue = request.getHeader(headerKey);
           metadata.put(headerKey, headerValue);
           }
          
           Map urlParams = request.getParameterMap();
           metadata.putAll(urlParams);
          
           String requestContentType = request.getContentType();
          
          
           try
           {
           Object invocationResponse = null;
          
           ServletInputStream inputStream = request.getInputStream();
           UnMarshaller unmarshaller = MarshalFactory.getUnMarshaller(HTTPUnMarshaller.DATATYPE);
           Object obj = unmarshaller.read(new ByteArrayInputStream(requestByte), metadata);
           inputStream.close();
          
           InvocationRequest invocationRequest = null;
          
           if(obj instanceof InvocationRequest)
           {
           invocationRequest = (InvocationRequest) obj;
           }
           else
           {
           if(isBinary(requestContentType))
           {
           invocationRequest = getInvocationRequest(metadata, obj);
           }
           else
           {
           invocationRequest = createNewInvocationRequest(metadata, obj);
           }
           }
          
           try
           {
           // call transport on the subclass, get the result to handback
           invocationResponse = invoke(invocationRequest);
           }
           catch(Throwable ex)
           {
           log.debug("Error thrown calling invoke on server invoker.", ex);
           invocationResponse = null;
           response.sendError(500, "Error processing invocation request. " + ex.getMessage());
           }
          
           if(invocationResponse != null)
           {
           response.setContentType(requestContentType);
           int iContentLength = getContentLength(invocationResponse);
           response.setContentLength(iContentLength);
           ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
           Marshaller marshaller = MarshalFactory.getMarshaller(HTTPMarshaller.DATATYPE);
           marshaller.write(invocationResponse, outputStream);
           retval = outputStream.toByteArray();
           }
          
           }
           catch(ClassNotFoundException e)
           {
           log.error("Error processing invocation request due to class not being found.", e);
           response.sendError(500, "Error processing invocation request due to class not being found. " + e.getMessage());
           }
          
           return retval;
           }
          
          




          • 2. Re: Bug in sertvlet remote transport.

            This has been fixed for 1.4.0 final release (see jira issue JBREM-282).