Bug in sertvlet remote transport.
dreyk Nov 2, 2005 10:00 AMServlet 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.