axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Firas Khasawneh \(fkhasawn\)" <fkhas...@cisco.com>
Subject RE: measuring Axix 1.4 overhead
Date Tue, 24 Jul 2007 16:22:34 GMT
Hi Jaliya,
 
To use Axis2 do  I need to change anything in my service code or rebuild
it or can I just replace the library jars?
 
Thanks,
Firas

________________________________

From: Jaliya Ekanayake [mailto:jnekanayake@gmail.com] 
Sent: Tuesday, July 24, 2007 10:44 AM
To: Firas Khasawneh (fkhasawn)
Cc: axis-dev@ws.apache.org
Subject: Re: measuring Axix 1.4 overhead


Hi Firas,
 
Did you try Axis2 http://ws.apache.org/axis2/ ?
In axis2 processing starts without fully building the soap envelope.
And the performance figures for Axis2 is http://www.wso2.org/library/588
 
Thanks,
-jaliya
 

	----- Original Message ----- 
	From: Firas Khasawneh (fkhasawn) <mailto:fkhasawn@cisco.com>  
	To: Jaliya Ekanayake <mailto:jaliya@apache.org>  
	Sent: Tuesday, July 24, 2007 8:48 AM
	Subject: RE: measuring Axix 1.4 overhead

	Hi Jaliya,
	 
	I tested with small size messages and 1 mb messages and there is
big difference, looks like Axis takes long time to process large
messages, but t4-t0 should give the processing time and not the
transport time. Also invoke time t3-t0 should give only Axis engine
overhead.
	 
	Thanks,
	Firas

________________________________

	From: Jaliya Ekanayake [mailto:jnekanayake@gmail.com] 
	Sent: Monday, July 23, 2007 4:34 PM
	To: Firas Khasawneh (fkhasawn)
	Subject: Re: measuring Axix 1.4 overhead
	
	
	Hi Firas,
	 
	Yes, t4-t0 should give you the results.
	However the problem is that you use large message size.
	My guess is that the processing happens before the total
retrieval of the message and hence it include the time it takes to
transfer the message as well.
	Did you try with a small message sizes?
	 
	Thanks,
	-jaliya

		----- Original Message ----- 
		From: Firas Khasawneh (fkhasawn)
<mailto:fkhasawn@cisco.com>  
		To: Jaliya Ekanayake <mailto:jaliya@apache.org>  ;
axis-user@ws.apache.org 
		Sent: Monday, July 23, 2007 3:49 PM
		Subject: RE: measuring Axix 1.4 overhead

		Hi Jaliya,
		 
		I am attaching the AxisServlet.java after adding
benchmark times, if you look at line 791 in the doPost method, the
invoke shoudl calculate the invokation time for the Axis engine without
the network time but for some reason it looks like it is including this
time in the invokation time which does not make any sense. I am testing
with 1 MB size files so I am not sure. below is AxisServlet.java, sorry
for cuttin and pasting it here but I was not sure if this email list
allows attachments:
		 
		/*

		* Copyright 2001-2004 The Apache Software Foundation.

		*

		* Licensed under the Apache License, Version 2.0 (the
"License");

		* you may not use this file except in compliance with
the License.

		* You may obtain a copy of the License at

		*

		* http://www.apache.org/licenses/LICENSE-2.0

		*

		* Unless required by applicable law or agreed to in
writing, software

		* distributed under the License is distributed on an "AS
IS" BASIS,

		* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied.

		* See the License for the specific language governing
permissions and

		* limitations under the License.

		*/

		

		package org.apache.axis.transport.http;

		

		import java.io.File;

		import java.io.IOException;

		import java.io.PrintWriter;

		import java.lang.reflect.Method;

		import java.lang.reflect.InvocationTargetException;

		import java.net.HttpURLConnection;

		import java.util.ArrayList;

		import java.util.Enumeration;

		import java.util.Iterator;

		

		import javax.servlet.ServletContext;

		import javax.servlet.ServletException;

		import javax.servlet.http.HttpServletRequest;

		import javax.servlet.http.HttpServletResponse;

		import javax.servlet.http.HttpUtils;

		import javax.xml.soap.MimeHeader;

		import javax.xml.soap.MimeHeaders;

		import javax.xml.soap.SOAPException;

		import javax.xml.soap.SOAPMessage;

		

		import org.apache.axis.AxisEngine;

		import org.apache.axis.AxisFault;

		import org.apache.axis.ConfigurationException;

		import org.apache.axis.Constants;

		import org.apache.axis.Handler;

		import org.apache.axis.Message;

		import org.apache.axis.MessageContext;

		import org.apache.axis.SimpleTargetedChain;

		import org.apache.axis.client.Service;

		import org.apache.axis.management.ServiceAdmin;

		import org.apache.axis.components.logger.LogFactory;

		import org.apache.axis.description.OperationDesc;

		import org.apache.axis.description.ServiceDesc;

		import org.apache.axis.handlers.soap.SOAPService;

		import
org.apache.axis.security.servlet.ServletSecurityProvider;

		import org.apache.axis.utils.JavaUtils;

		import org.apache.axis.utils.Messages;

		import org.apache.axis.utils.XMLUtils;

		import org.apache.commons.logging.Log;

		import org.w3c.dom.Element;

		

		/**

		*

		* @author Doug Davis (dug@us.ibm.com)

		* @author Steve Loughran

		* xdoclet tags are not active yet; keep web.xml in sync.

		* To change the location of the services, change
url-pattern in web.xml and

		* set parameter axis.servicesPath in server-config.wsdd.
For more information see

		* <a
href="http://ws.apache.org/axis/java/reference.html">Axis Reference
Guide</a>.

		*

		* @web.servlet name="AxisServlet"
display-name="Apache-Axis Servlet"

		* @web.servlet-mapping
url-pattern="/servlet/AxisServlet"

		* @web.servlet-mapping url-pattern="*.jws"

		* @web.servlet-mapping url-pattern="/services/*"

		*/

		public class AxisServlet extends AxisServletBase {

		protected static Log log =

		LogFactory.getLog(AxisServlet.class.getName());

		

		/**

		* this log is for timing

		*/

		private static Log tlog =

		LogFactory.getLog(Constants.TIME_LOG_CATEGORY);

		

		/**

		* a separate log for exceptions lets users route them

		* differently from general low level debug info

		*/

		private static Log exceptionLog =

		LogFactory.getLog(Constants.EXCEPTION_LOG_CATEGORY);

		

		public static final String INIT_PROPERTY_TRANSPORT_NAME
=

		"transport.name";

		

		public static final String INIT_PROPERTY_USE_SECURITY =

		"use-servlet-security";

		public static final String INIT_PROPERTY_ENABLE_LIST =

		"axis.enableListQuery";

		

		public static final String INIT_PROPERTY_JWS_CLASS_DIR =

		"axis.jws.servletClassDir";

		

		// This will turn off the list of available services

		public static final String
INIT_PROPERTY_DISABLE_SERVICES_LIST =

		"axis.disableServiceList";

		

		// Location of the services as defined by the
servlet-mapping in web.xml

		public static final String INIT_PROPERTY_SERVICES_PATH =

		"axis.servicesPath";

		

		// These have default values.

		private String transportName;

		

		private Handler transport;

		

		private ServletSecurityProvider securityProvider = null;

		

		private String servicesPath;

		

		/**

		* cache of logging debug option; only evaluated at init
time.

		* So no dynamic switching of logging options with this
servlet.

		*/

		private static boolean isDebug = false;

		

		/**

		* Should we enable the "?list" functionality on GETs?
(off by

		* default because deployment information is a potential
security

		* hole)

		*/

		private boolean enableList = false;

		

		/**

		* Should we turn off the list of services when we
receive a GET

		* at the servlet root?

		*/

		private boolean disableServicesList = false;

		

		/**

		* Cached path to JWS output directory

		*/

		private String jwsClassDir = null;

		protected String getJWSClassDir() {return jwsClassDir;

		}

		

		 

		/**

		* create a new servlet instance

		*/

		public AxisServlet() {

		}

		

		/**

		* Initialization method.

		*/

		public void init() throws javax.servlet.ServletException
{

		super.init();

		ServletContext context =
getServletConfig().getServletContext();

		

		isDebug = log.isDebugEnabled();

		if (isDebug) {

		log.debug("In servlet init");

		}

		transportName = getOption(context,

		INIT_PROPERTY_TRANSPORT_NAME,

		HTTPTransport.DEFAULT_TRANSPORT_NAME);

		

		if (JavaUtils.isTrueExplicitly(getOption(context,

		INIT_PROPERTY_USE_SECURITY, null))) {

		securityProvider = new ServletSecurityProvider();

		}

		

		enableList =

		JavaUtils.isTrueExplicitly(getOption(context,

		INIT_PROPERTY_ENABLE_LIST, null));

		

		jwsClassDir = getOption(context,
INIT_PROPERTY_JWS_CLASS_DIR, null);

		

		// Should we list services?

		disableServicesList =
JavaUtils.isTrue(getOption(context,

		INIT_PROPERTY_DISABLE_SERVICES_LIST, "false"));

		

		servicesPath = getOption(context,
INIT_PROPERTY_SERVICES_PATH,

		"/services/");

		

		/**

		* There are DEFINATE problems here if

		* getHomeDir and/or getDefaultJWSClassDir return null

		* (as they could with WebLogic).

		* This needs to be reexamined in the future, but this

		* should fix any NPE's in the mean time.

		*/

		if (jwsClassDir != null) {

		if (getHomeDir() != null) {

		jwsClassDir = getHomeDir() + jwsClassDir;

		}

		} else {

		jwsClassDir = getDefaultJWSClassDir();

		}

		

		initQueryStringHandlers();

		

		// Setup the service admin

		try {

		ServiceAdmin.setEngine(this.getEngine(),
context.getServerInfo());

		} catch (AxisFault af) {

		exceptionLog.info("Exception setting AxisEngine on
ServiceAdmin " +

		af);

		}

		}

		

		 

		/**

		* Process GET requests. This includes handoff of
pseudo-SOAP requests

		*

		* @param request request in

		* @param response request out

		* @throws ServletException

		* @throws IOException

		*/

		public void doGet(HttpServletRequest request,
HttpServletResponse response) throws

		ServletException, IOException {

		if (isDebug) {

		log.debug("Enter: doGet()");

		

		}

		PrintWriter writer = new FilterPrintWriter(response);

		

		try {

		AxisEngine engine = getEngine();

		ServletContext servletContext =

		getServletConfig().getServletContext();

		

		String pathInfo = request.getPathInfo();

		String realpath =
servletContext.getRealPath(request.getServletPath());

		if (realpath == null) {

		realpath = request.getServletPath();

		}

		

		//JWS pages are special; they are the servlet path and
there

		//is no pathinfo...we map the pathinfo to the servlet
path to keep

		//it happy

		boolean isJWSPage =
request.getRequestURI().endsWith(".jws");

		if (isJWSPage) {

		pathInfo = request.getServletPath();

		}

		

		// Try to execute a query string plugin and return upon
success.

		

		if (processQuery(request, response, writer) == true) {

		long reqout = System.currentTimeMillis();

		return;

		}

		

		boolean hasNoPath = (pathInfo == null ||
pathInfo.equals(""));

		if (!disableServicesList) {

		if(hasNoPath) {

		// If the user requested the servlet (i.e.
/axis/servlet/AxisServlet)

		// with no service name, present the user with a list of
deployed

		// services to be helpful

		// Don't do this if has been turned off

		reportAvailableServices(response, writer, request);

		} else if (realpath != null) {

		// We have a pathname, so now we perform WSDL or list
operations

		

		// get message context w/ various properties set

		MessageContext msgContext = createMessageContext(engine,

		request, response);

		

		// NOTE: HttpUtils.getRequestURL has been deprecated.

		// This line SHOULD be:

		// String url = req.getRequestURL().toString()

		// HOWEVER!!!! DON'T REPLACE IT! There's a bug in

		// req.getRequestURL that is not in
HttpUtils.getRequestURL

		// req.getRequestURL returns "localhost" in the remote

		// scenario rather than the actual host name.

		//

		// But more importantly, getRequestURL() is a servlet
2.3

		// API and to support servlet 2.2 (aka WebSphere 4)

		// we need to leave this in for a while longer. tomj
10/14/2004

		//

		String url =
HttpUtils.getRequestURL(request).toString();

		

		msgContext.setProperty(MessageContext.TRANS_URL, url);

		

		// See if we can locate the desired service. If we

		// can't, return a 404 Not Found. Otherwise, just

		// print the placeholder message.

		

		String serviceName;

		if (pathInfo.startsWith("/")) {

		serviceName = pathInfo.substring(1);

		} else {

		serviceName = pathInfo;

		}

		

		SOAPService s = engine.getService(serviceName);

		if (s == null) {

		//no service: report it

		if (isJWSPage) {

		reportCantGetJWSService(request, response, writer);

		} else {

		reportCantGetAxisService(request, response, writer);

		}

		

		} else {

		//print a snippet of service info.

		reportServiceInfo(response, writer, s, serviceName);

		}

		}

		} else {

		// We didn't have a real path in the request, so just

		// print a message informing the user that they reached

		// the servlet.

		

		response.setContentType("text/html; charset=utf-8");

		writer.println("<html><h1>Axis HTTP Servlet</h1>");

		writer.println(Messages.getMessage("reachedServlet00"));

		

		writer.println("<p>" +

		Messages.getMessage("transportName00",

		"<b>" + transportName + "</b>"));

		writer.println("</html>");

		}

		} catch (AxisFault fault) {

		reportTroubleInGet(fault, response, writer);

		} catch (Exception e) {

		reportTroubleInGet(e, response, writer);

		} finally {

		writer.close();

		if (isDebug) {

		log.debug("Exit: doGet()");

		}

		}

		}

		

		/**

		* when we get an exception or an axis fault in a GET, we
handle

		* it almost identically: we go 'something went wrong',
set the response

		* code to 500 and then dump info. But we dump different
info for an axis fault

		* or subclass thereof.

		* @param exception what went wrong

		* @param response current response

		* @param writer open writer to response

		*/

		private void reportTroubleInGet(Throwable exception,

		HttpServletResponse response,

		PrintWriter writer) {

		response.setContentType("text/html; charset=utf-8");

	
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

		writer.println("<h2>" +

		Messages.getMessage("error00") +

		"</h2>");

		writer.println("<p>" +

		Messages.getMessage("somethingWrong00") +

		"</p>");

		if (exception instanceof AxisFault) {

		AxisFault fault = (AxisFault) exception;

		processAxisFault(fault);

		writeFault(writer, fault);

		} else {

		logException(exception);

		writer.println("<pre>Exception - " + exception +
"<br>");

		//dev systems only give fault dumps

		if (isDevelopment()) {

		writer.println(JavaUtils.stackToString(exception));

		}

		writer.println("</pre>");

		}

		}

		

		/**

		* routine called whenever an axis fault is caught; where
they

		* are logged and any other business. The method may
modify the fault

		* in the process

		* @param fault what went wrong.

		*/

		protected void processAxisFault(AxisFault fault) {

		//log the fault

		Element runtimeException = fault.lookupFaultDetail(

		Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);

		if (runtimeException != null) {

		exceptionLog.info(Messages.getMessage("axisFault00"),
fault);

		//strip runtime details

		fault.removeFaultDetail(Constants.

		QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);

		} else if (exceptionLog.isDebugEnabled()) {

		exceptionLog.debug(Messages.getMessage("axisFault00"),
fault);

		}

		//dev systems only give fault dumps

		if (!isDevelopment()) {

		//strip out the stack trace

	
fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE);

		}

		}

		

		/**

		* log any exception to our output log, at our chosen
level

		* @param e what went wrong

		*/

		protected void logException(Throwable e) {

		exceptionLog.info(Messages.getMessage("exception00"),
e);

		}

		

		/**

		* this method writes a fault out to an HTML stream. This
includes

		* escaping the strings to defend against cross-site
scripting attacks

		* @param writer

		* @param axisFault

		*/

		private void writeFault(PrintWriter writer, AxisFault
axisFault) {

		String localizedMessage =
XMLUtils.xmlEncodeString(axisFault.

		getLocalizedMessage());

		writer.println("<pre>Fault - " + localizedMessage +
"<br>");

		writer.println(axisFault.dumpToString());

		writer.println("</pre>");

		}

		

		/**

		* print a snippet of service info.

		* @param service service

		* @param writer output channel

		* @param serviceName where to put stuff

		*/

		

		protected void reportServiceInfo(HttpServletResponse
response,

		PrintWriter writer, SOAPService service,

		String serviceName) {

		response.setContentType("text/html; charset=utf-8");

		

		writer.println("<h1>"

		+ service.getName()

		+ "</h1>");

		writer.println(

		"<p>" +

		Messages.getMessage("axisService00") +

		"</p>");

		writer.println(

		"<i>" +

		Messages.getMessage("perhaps00") +

		"</i>");

		}

		

		/**

		* report that we have no WSDL

		*

		* This method was moved to the querystring handler
QSWSDLHandler. The

		* method reportNoWSDL in AxisServlet is never called.
Perhaps the method

		* is overwritten in subclasses of AxisServlet so the
method wasn't

		* removed. See the discussion in

		*

		*
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23845

		*

		* @param res

		* @param writer

		* @param moreDetailCode optional name of a message to
provide more detail

		* @param axisFault optional fault string, for extra info
at debug time only

		*/

		protected void reportNoWSDL(HttpServletResponse res,
PrintWriter writer,

		String moreDetailCode, AxisFault axisFault) {

		}

		

		 

		/**

		* This method lists the available services; it is called
when there is

		* nothing to execute on a GET

		* @param response

		* @param writer

		* @param request

		* @throws ConfigurationException

		* @throws AxisFault

		*/

		protected void
reportAvailableServices(HttpServletResponse response,

		PrintWriter writer,

		HttpServletRequest request) throws

		ConfigurationException, AxisFault {

		AxisEngine engine = getEngine();

		

		response.setContentType("text/html; charset=utf-8");

		writer.println("<h2>And now... Some Services</h2>");

		

		Iterator i;

		try {

		i = engine.getConfig().getDeployedServices();

		} catch (ConfigurationException configException) {

		//turn any internal configuration exceptions back into
axis faults

		//if that is what they are

		if (configException.getContainedException() instanceof
AxisFault) {

		throw (AxisFault)
configException.getContainedException();

		} else {

		throw configException;

		}

		}

		// baseURL may change if <endpointURL> tag is used for

		// custom deployment at a different location

		String defaultBaseURL = getWebappBase(request) +
servicesPath;

		writer.println("<ul>");

		while (i.hasNext()) {

		ServiceDesc sd = (ServiceDesc) i.next();

		StringBuffer sb = new StringBuffer();

		sb.append("<li>");

		String name = sd.getName();

		sb.append(name);

		sb.append(" <a href=\"");

		String endpointURL = sd.getEndpointURL();

		String baseURL = (endpointURL == null) ? defaultBaseURL
:

		endpointURL;

		sb.append(baseURL);

		sb.append(name);

		sb.append("?wsdl\"><i>(wsdl)</i></a></li>");

		writer.println(sb.toString());

		ArrayList operations = sd.getOperations();

		if (!operations.isEmpty()) {

		writer.println("<ul>");

		for (Iterator it = operations.iterator(); it.hasNext();
) {

		OperationDesc desc = (OperationDesc) it.next();

		writer.println("<li>" + desc.getName());

		}

		writer.println("</ul>");

		}

		}

		writer.println("</ul>");

		}

		

		/**

		* generate the error response to indicate that there is
apparently no endpoint there

		* @param request the request that didnt have an edpoint

		* @param response response we are generating

		* @param writer open writer for the request

		*/

		protected void
reportCantGetAxisService(HttpServletRequest request,

		HttpServletResponse response,

		PrintWriter writer) {

		// no such service....

		response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);

		response.setContentType("text/html; charset=utf-8");

		writer.println("<h2>" +

		Messages.getMessage("error00") + "</h2>");

		writer.println("<p>" +

		Messages.getMessage("noService06") +

		"</p>");

		}

		

		/**

		* probe for a JWS page and report 'no service' if one is
not found there

		* @param request the request that didnt have an edpoint

		* @param response response we are generating

		* @param writer open writer for the request

		*/

		protected void
reportCantGetJWSService(HttpServletRequest request,

		HttpServletResponse response,

		PrintWriter writer) {

		// first look to see if there is a service

		// requestPath is a work around to support serving .jws
web services

		// from services URL - see AXIS-843 for more information

		String requestPath = request.getServletPath() +
((request.getPathInfo() != null) ?

		request.getPathInfo() : "");

		String realpath = getServletConfig().getServletContext()

		.getRealPath(requestPath);

		log.debug("JWS real path: " + realpath);

		boolean foundJWSFile = (new File(realpath).exists()) &&

		(realpath.endsWith(Constants.

		JWS_DEFAULT_FILE_EXTENSION));

		response.setContentType("text/html; charset=utf-8");

		if (foundJWSFile) {

		response.setStatus(HttpURLConnection.HTTP_OK);

		writer.println(Messages.getMessage("foundJWS00") +
"<p>");

		String url = request.getRequestURI();

		String urltext = Messages.getMessage("foundJWS01");

		writer.println("<a href='" + url + "?wsdl'>" + urltext +
"</a>");

		} else {

		response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);

		writer.println(Messages.getMessage("noService06"));

		}

		}

		

		 

		/**

		* Process a POST to the servlet by handing it off to the
Axis Engine.

		* Here is where SOAP messages are received

		* @param req posted request

		* @param res respose

		* @throws ServletException trouble

		* @throws IOException different trouble

		*/

		public void doPost(HttpServletRequest req,
HttpServletResponse res) throws

		ServletException, IOException {

		long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;

		String soapAction = null;

		MessageContext msgContext = null;

		if (isDebug) {

		log.debug("Enter: doPost()");

		}

		t0 = System.currentTimeMillis();

		if (tlog.isDebugEnabled()) {

		t0 = System.currentTimeMillis();

		}

		

		Message responseMsg = null;

		String contentType = null;

		

		try {

		AxisEngine engine = getEngine();

		

		if (engine == null) {

		// !!! should return a SOAP fault...

		ServletException se =

		new ServletException(Messages.getMessage("noEngine00"));

		log.debug("No Engine!", se);

		throw se;

		}

		

		res.setBufferSize(1024 * 8); // provide performance
boost.

		

		/** get message context w/ various properties set

		*/

		msgContext = createMessageContext(engine, req, res);

		

		// ? OK to move this to 'getMessageContext',

		// ? where it would also be picked up for 'doGet()' ?

		if (securityProvider != null) {

		if (isDebug) {

		log.debug("securityProvider:" + securityProvider);

		}

		msgContext.setProperty(MessageContext.SECURITY_PROVIDER,

		securityProvider);

		}

		

		/* Get request message

		*/

		Message requestMsg =

		new Message(req.getInputStream(),

		false,

		req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE),

		req.getHeader(HTTPConstants.

		HEADER_CONTENT_LOCATION));

		// Transfer HTTP headers to MIME headers for request
message.

		MimeHeaders requestMimeHeaders =
requestMsg.getMimeHeaders();

		for (Enumeration e = req.getHeaderNames();
e.hasMoreElements(); ) {

		String headerName = (String) e.nextElement();

		for (Enumeration f = req.getHeaders(headerName);

		f.hasMoreElements(); ) {

		String headerValue = (String) f.nextElement();

		requestMimeHeaders.addHeader(headerName, headerValue);

		}

		}

		

		if (isDebug) {

		log.debug("Request Message:" + requestMsg);

		

		/* Set the request(incoming) message field in the
context */

	
/**********************************************************/

		}

		msgContext.setRequestMessage(requestMsg);

		String url = HttpUtils.getRequestURL(req).toString();

		msgContext.setProperty(MessageContext.TRANS_URL, url);

		// put character encoding of request to message context

		// in order to reuse it during the whole process.

		String requestEncoding;

		try {

		requestEncoding = (String)
requestMsg.getProperty(SOAPMessage.

		CHARACTER_SET_ENCODING);

		if (requestEncoding != null) {

	
msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING,

		requestEncoding);

		}

		} catch (SOAPException e1) {

		}

		

		try {

		/**

		* Save the SOAPAction header in the MessageContext bag.

		* This will be used to tell the Axis Engine which
service

		* is being invoked. This will save us the trouble of

		* having to parse the Request message - although we will

		* need to double-check later on that the SOAPAction
header

		* does in fact match the URI in the body.

		*/

		// (is this last stmt true??? (I don't think so - Glen))

	
/********************************************************/

		soapAction = getSoapAction(req);

		

		if (soapAction != null) {

		msgContext.setUseSOAPAction(true);

		msgContext.setSOAPActionURI(soapAction);

		}

		

		// Create a Session wrapper for the HTTP session.

		// These can/should be pooled at some point.

		// (Sam is Watching! :-)

		msgContext.setSession(new AxisHttpSession(req));

		t1 = System.currentTimeMillis();

		if (tlog.isDebugEnabled()) {

		t1 = System.currentTimeMillis();

		}

		/* Invoke the Axis engine... */

		/*****************************/

		if (isDebug) {

		log.debug("Invoking Axis Engine.");

		//here we run the message by the engine

		}

		engine.invoke(msgContext);

		if (isDebug) {

		log.debug("Return from Axis Engine.");

		}

		t2 = System.currentTimeMillis();

		if (tlog.isDebugEnabled()) {

		t2 = System.currentTimeMillis();

		}

		responseMsg = msgContext.getResponseMessage();

		

		// We used to throw exceptions on null response
messages.

		// They are actually OK in certain situations
(asynchronous

		// services), so fall through here and return an
ACCEPTED

		// status code below. Might want to install a
configurable

		// error check for this later.

		} catch (AxisFault fault) {

		//log and sanitize

		processAxisFault(fault);

		configureResponseFromAxisFault(res, fault);

		responseMsg = msgContext.getResponseMessage();

		if (responseMsg == null) {

		responseMsg = new Message(fault);

		((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).

		getMessage().setMessageContext(msgContext);

		}

		} catch (Exception e) {

		//other exceptions are internal trouble

		responseMsg = msgContext.getResponseMessage();

	
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

		responseMsg = convertExceptionToAxisFault(e,
responseMsg);

		((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).

		getMessage().setMessageContext(msgContext);

		} catch (Throwable t) {

		logException(t);

		//other exceptions are internal trouble

		responseMsg = msgContext.getResponseMessage();

	
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

		responseMsg = new Message(new
AxisFault(t.toString(),t));

		((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).

		getMessage().setMessageContext(msgContext);

		}

		} catch (AxisFault fault) {

		processAxisFault(fault);

		configureResponseFromAxisFault(res, fault);

		responseMsg = msgContext.getResponseMessage();

		if (responseMsg == null) {

		responseMsg = new Message(fault);

		((org.apache.axis.SOAPPart) responseMsg.getSOAPPart()).

		getMessage().setMessageContext(msgContext);

		}

		}

		t3 = System.currentTimeMillis();

		if (tlog.isDebugEnabled()) {

		t3 = System.currentTimeMillis();

		}

		

		/* Send response back along the wire... */

		/***********************************/

		if (responseMsg != null) {

		// Transfer MIME headers to HTTP headers for response
message.

		MimeHeaders responseMimeHeaders =
responseMsg.getMimeHeaders();

		for (Iterator i = responseMimeHeaders.getAllHeaders();
i.hasNext(); ) {

		MimeHeader responseMimeHeader = (MimeHeader) i.next();

		res.addHeader(responseMimeHeader.getName(),

		responseMimeHeader.getValue());

		}

		// synchronize the character encoding of request and
response

		String responseEncoding = (String)
msgContext.getProperty(

		SOAPMessage.CHARACTER_SET_ENCODING);

		if (responseEncoding != null) {

		try {

	
responseMsg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING,

		responseEncoding);

		} catch (SOAPException e) {

		}

		}

		//determine content type from message response

		contentType = responseMsg.getContentType(msgContext.

		getSOAPConstants());

		sendResponse(contentType, res, responseMsg);

		} else {

		// No content, so just indicate accepted

		res.setStatus(202);

		}

		

		if (isDebug) {

		log.debug("Response sent.");

		log.debug("Exit: doPost()");

		}

		t4 = System.currentTimeMillis();

		System.out.println("Axis stats: " +

		" pre=" + (t1 - t0) +

		" invoke=" + (t2 - t1) +

		" post=" + (t3 - t2) +

		" send=" + (t4 - t3) +

		" total=" + (t4 - t0));

		if (tlog.isDebugEnabled()) {

		t4 = System.currentTimeMillis();

		tlog.debug("axisServlet.doPost: " + soapAction +

		" pre=" + (t1 - t0) +

		" invoke=" + (t2 - t1) +

		" post=" + (t3 - t2) +

		" send=" + (t4 - t3) +

		" " + msgContext.getTargetService() + "." +

		((msgContext.getOperation() == null) ?

		"" : msgContext.getOperation().getName()));

		}

		

		}

		

		/**

		* Configure the servlet response status code and maybe
other headers

		* from the fault info.

		* @param response response to configure

		* @param fault what went wrong

		*/

		private void
configureResponseFromAxisFault(HttpServletResponse response,

		AxisFault fault) {

		// then get the status code

		// It's been suggested that a lack of SOAPAction

		// should produce some other error code (in the 400s)...

		int status = getHttpServletResponseStatus(fault);

		if (status == HttpServletResponse.SC_UNAUTHORIZED) {

		// unauth access results in authentication request

		// TODO: less generic realm choice?

		response.setHeader("WWW-Authenticate", "Basic
realm=\"AXIS\"");

		}

		response.setStatus(status);

		}

		

		/**

		* turn any Exception into an AxisFault, log it, set the
response

		* status code according to what the specifications say
and

		* return a response message for posting. This will be
the response

		* message passed in if non-null; one generated from the
fault otherwise.

		*

		* @param exception what went wrong

		* @param responseMsg what response we have (if any)

		* @return a response message to send to the user

		*/

		private Message convertExceptionToAxisFault(Exception
exception,

		Message responseMsg) {

		logException(exception);

		if (responseMsg == null) {

		AxisFault fault = AxisFault.makeFault(exception);

		processAxisFault(fault);

		responseMsg = new Message(fault);

		}

		return responseMsg;

		}

		

		/**

		* Extract information from AxisFault and map it to a
HTTP Status code.

		*

		* @param af Axis Fault

		* @return HTTP Status code.

		*/

		protected int getHttpServletResponseStatus(AxisFault af)
{

		// TODO: Should really be doing this with explicit
AxisFault

		// subclasses... --Glen

		return
af.getFaultCode().getLocalPart().startsWith("Server.Unauth")

		? HttpServletResponse.SC_UNAUTHORIZED

		: HttpServletResponse.SC_INTERNAL_SERVER_ERROR;

		// This will raise a 401 for both

		// "Unauthenticated" & "Unauthorized"...

		}

		

		/**

		* write a message to the response, set appropriate
headers for content

		* type..etc.

		* @param res response

		* @param responseMsg message to write

		* @throws AxisFault

		* @throws IOException if the response stream can not be
written to

		*/

		private void sendResponse(String contentType,

		HttpServletResponse res,

		Message responseMsg) throws AxisFault,

		IOException {

		if (responseMsg == null) {

		res.setStatus(HttpServletResponse.SC_NO_CONTENT);

		if (isDebug) {

		log.debug("NO AXIS MESSAGE TO RETURN!");

		//String resp = Messages.getMessage("noData00");

		//res.setContentLength((int) resp.getBytes().length);

		//res.getWriter().print(resp);

		}

		} else {

		if (isDebug) {

		log.debug("Returned Content-Type:" +

		contentType);

		// log.debug("Returned Content-Length:" +

		// responseMsg.getContentLength());

		}

		

		try {

		res.setContentType(contentType);

		

		/* My understand of Content-Length

		* HTTP 1.0

		* -Required for requests, but optional for responses.

		* HTTP 1.1

		* - Either Content-Length or HTTP Chunking is required.

		* Most servlet engines will do chunking if
content-length is not specified.

		*

		*

		*/

		

		//if(clientVersion == HTTPConstants.HEADER_PROTOCOL_V10)
//do chunking if necessary.

		// res.setContentLength(responseMsg.getContentLength());

		

		responseMsg.writeTo(res.getOutputStream());

		} catch (SOAPException e) {

		logException(e);

		}

		}

		

		if (!res.isCommitted()) {

		res.flushBuffer(); // Force it right now.

		}

		}

		

		/**

		* Place the Request message in the MessagContext object
- notice

		* that we just leave it as a 'ServletRequest' object and
let the

		* Message processing routine convert it - we don't do it
since we

		* don't know how it's going to be used - perhaps it
might not

		* even need to be parsed.

		* @return a message context

		*/

		private MessageContext createMessageContext(AxisEngine
engine,

		HttpServletRequest req,

		HttpServletResponse res) {

		MessageContext msgContext = new MessageContext(engine);

		

		String requestPath = getRequestPath(req);

		

		if (isDebug) {

		log.debug("MessageContext:" + msgContext);

		log.debug("HEADER_CONTENT_TYPE:" +

		req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE));

		log.debug("HEADER_CONTENT_LOCATION:" +

		req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));

		log.debug("Constants.MC_HOME_DIR:" +
String.valueOf(getHomeDir()));

		log.debug("Constants.MC_RELATIVE_PATH:" + requestPath);

		log.debug("HTTPConstants.MC_HTTP_SERVLETLOCATION:" +

		String.valueOf(getWebInfPath()));

		log.debug("HTTPConstants.MC_HTTP_SERVLETPATHINFO:" +

		req.getPathInfo());

		log.debug("HTTPConstants.HEADER_AUTHORIZATION:" +

		req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));

		log.debug("Constants.MC_REMOTE_ADDR:" +
req.getRemoteAddr());

		log.debug("configPath:" +
String.valueOf(getWebInfPath()));

		}

		

		/* Set the Transport */

		/*********************/

		msgContext.setTransportName(transportName);

		

		/* Save some HTTP specific info in the bag in case
someone needs it */

	
/********************************************************************/

		msgContext.setProperty(Constants.MC_JWS_CLASSDIR,
jwsClassDir);

		msgContext.setProperty(Constants.MC_HOME_DIR,
getHomeDir());

		msgContext.setProperty(Constants.MC_RELATIVE_PATH,
requestPath);

		msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET,
this);

	
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req);

	
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res);

	
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION,

		getWebInfPath());

	
msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO,

		req.getPathInfo());

	
msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION,

		req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));

		msgContext.setProperty(Constants.MC_REMOTE_ADDR,
req.getRemoteAddr());

		

		// Set up a javax.xml.rpc.server.ServletEndpointContext

		ServletEndpointContextImpl sec = new
ServletEndpointContextImpl();

		

	
msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);

		/* Save the real path */

		/**********************/

		String realpath = getServletConfig().getServletContext()

		.getRealPath(requestPath);

		

		if (realpath != null) {

		msgContext.setProperty(Constants.MC_REALPATH, realpath);

		}

		

		msgContext.setProperty(Constants.MC_CONFIGPATH,
getWebInfPath());

		

		return msgContext;

		}

		

		/**

		* Extract the SOAPAction header.

		* if SOAPAction is null then we'll we be forced to scan
the body for it.

		* if SOAPAction is "" then use the URL

		* @param req incoming request

		* @return the action

		* @throws AxisFault

		*/

		private String getSoapAction(HttpServletRequest req)
throws AxisFault {

		String soapAction =
req.getHeader(HTTPConstants.HEADER_SOAP_ACTION);

		if (soapAction == null) {

		String contentType =
req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);

		if(contentType != null) {

		int index = contentType.indexOf("action");

		if(index != -1){

		soapAction = contentType.substring(index + 7);

		}

		}

		}

		

		if (isDebug) {

		log.debug("HEADER_SOAP_ACTION:" + soapAction);

		

		/**

		* Technically, if we don't find this header, we should
probably fault.

		* It's required in the SOAP HTTP binding.

		*/

		}

		if (soapAction == null) {

		AxisFault af = new AxisFault("Client.NoSOAPAction",

		Messages.getMessage("noHeader00",

		"SOAPAction"),

		null, null);

		

		exceptionLog.error(Messages.getMessage("genFault00"),
af);

		

		throw af;

		}

		// the SOAP 1.1 spec & WS-I 1.0 says:

		// soapaction = "SOAPAction" ":" [ <"> URI-reference <">
]

		// some implementations leave off the quotes

		// we strip them if they are present

		if (soapAction.startsWith("\"") &&
soapAction.endsWith("\"")

		&& soapAction.length() >= 2) {

		int end = soapAction.length() - 1;

		soapAction = soapAction.substring(1, end);

		}

		

		if (soapAction.length() == 0) {

		soapAction = req.getContextPath(); // Is this right?

		

		}

		return soapAction;

		}

		

		/**

		* Provided to allow overload of default JWSClassDir

		* by derived class.

		* @return directory for JWS files

		*/

		protected String getDefaultJWSClassDir() {

		return (getWebInfPath() == null)

		? null // ??? what is a good FINAL default for WebLogic?

		: getWebInfPath() + File.separator + "jwsClasses";

		}

		

		/**

		* Initialize a Handler for the transport defined in the
Axis server config.

		* This includes optionally filling in query string
handlers.

		*/

		

		public void initQueryStringHandlers() {

		try {

		this.transport =
getEngine().getTransport(this.transportName);

		

		if (this.transport == null) {

		// No transport by this name is defined. Therefore, fill
in default

		// query string handlers.

		

		this.transport = new SimpleTargetedChain();

		

		this.transport.setOption("qs.list",

		"org.apache.axis.transport.http.QSListHandler");

		this.transport.setOption("qs.method",

		"org.apache.axis.transport.http.QSMethodHandler");

		this.transport.setOption("qs.wsdl",

		"org.apache.axis.transport.http.QSWSDLHandler");

		

		return;

		}

		

		else {

		// See if we should use the default query string
handlers.

		// By default, set this to true (for backwards
compatibility).

		

		boolean defaultQueryStrings = true;

		String useDefaults = (String)this.transport.getOption(

		"useDefaultQueryStrings");

		

		if ((useDefaults != null) &&

		useDefaults.toLowerCase().equals("false")) {

		defaultQueryStrings = false;

		}

		

		if (defaultQueryStrings == true) {

		// We should use defaults, so fill them in.

		

		this.transport.setOption("qs.list",

		"org.apache.axis.transport.http.QSListHandler");

		this.transport.setOption("qs.method",

		"org.apache.axis.transport.http.QSMethodHandler");

		this.transport.setOption("qs.wsdl",

		"org.apache.axis.transport.http.QSWSDLHandler");

		}

		}

		}

		

		catch (AxisFault e) {

		// Some sort of problem occurred, let's just make a
default transport.

		

		this.transport = new SimpleTargetedChain();

		

		this.transport.setOption("qs.list",

		"org.apache.axis.transport.http.QSListHandler");

		this.transport.setOption("qs.method",

		"org.apache.axis.transport.http.QSMethodHandler");

		this.transport.setOption("qs.wsdl",

		"org.apache.axis.transport.http.QSWSDLHandler");

		

		return;

		}

		}

		

		/**

		* Attempts to invoke a plugin for the query string
supplied in the URL.

		*

		* @param request the servlet's HttpServletRequest
object.

		* @param response the servlet's HttpServletResponse
object.

		* @param writer the servlet's PrintWriter object.

		*/

		

		private boolean processQuery(HttpServletRequest request,

		HttpServletResponse response,

		PrintWriter writer) throws AxisFault {

		// Attempt to instantiate a plug-in handler class for
the query string

		// handler classes defined in the HTTP transport.

		

		String path = request.getServletPath();

		String queryString = request.getQueryString();

		String serviceName;

		AxisEngine engine = getEngine();

		Iterator i =
this.transport.getOptions().keySet().iterator();

		

		if (queryString == null) {

		return false;

		}

		

		String servletURI = request.getContextPath() + path;

		String reqURI = request.getRequestURI();

		// chop off '/'.

		if (servletURI.length() + 1 < reqURI.length()) {

		serviceName = reqURI.substring(servletURI.length() + 1);

		} else {

		serviceName = "";

		} while (i.hasNext() == true) {

		String queryHandler = (String) i.next();

		

		if (queryHandler.startsWith("qs.") == true) {

		// Only attempt to match the query string with transport

		// parameters prefixed with "qs:".

		

		String handlerName = queryHandler.substring

		(queryHandler.indexOf(".") + 1).

		toLowerCase();

		

		// Determine the name of the plugin to invoke by using
all text

		// in the query string up to the first occurence of &,
=, or the

		// whole string if neither is present.

		

		int length = 0;

		boolean firstParamFound = false;

		

		while (firstParamFound == false && length <
queryString.length()) {

		char ch = queryString.charAt(length++);

		

		if (ch == '&' || ch == '=') {

		firstParamFound = true;

		

		--length;

		}

		}

		

		if (length < queryString.length()) {

		queryString = queryString.substring(0, length);

		}

		

		if (queryString.toLowerCase().equals(handlerName) ==
true) {

		// Query string matches a defined query string handler
name.

		

		// If the defined class name for this query string
handler is blank,

		// just return (the handler is "turned off" in effect).

		

		if (this.transport.getOption(queryHandler).equals("")) {

		return false;

		}

		

		try {

		// Attempt to dynamically load the query string handler

		// and its "invoke" method.

		

		MessageContext msgContext = createMessageContext(engine,

		request, response);

		Class plugin = Class.forName((String)this.transport.

		getOption(queryHandler));

		Method pluginMethod = plugin.getDeclaredMethod("invoke",

		new Class[] {msgContext.getClass()});

		String url =
HttpUtils.getRequestURL(request).toString();

		

		// Place various useful servlet-related objects in

		// the MessageContext object being delivered to the

		// plugin.

		msgContext.setProperty(MessageContext.TRANS_URL, url);

		msgContext.setProperty(HTTPConstants.

		PLUGIN_SERVICE_NAME, serviceName);

		msgContext.setProperty(HTTPConstants.PLUGIN_NAME,

		handlerName);

		msgContext.setProperty(HTTPConstants.

		PLUGIN_IS_DEVELOPMENT,

		new Boolean(isDevelopment()));

		msgContext.setProperty(HTTPConstants.PLUGIN_ENABLE_LIST,

		new Boolean(enableList));

		msgContext.setProperty(HTTPConstants.PLUGIN_ENGINE,

		engine);

		msgContext.setProperty(HTTPConstants.PLUGIN_WRITER,

		writer);

		msgContext.setProperty(HTTPConstants.PLUGIN_LOG, log);

		msgContext.setProperty(HTTPConstants.

		PLUGIN_EXCEPTION_LOG,

		exceptionLog);

		

		// Invoke the plugin.

		

		pluginMethod.invoke(plugin.newInstance(),

		new Object[] {msgContext});

		

		writer.close();

		

		return true;

		} catch (InvocationTargetException ie) {

		reportTroubleInGet(ie.getTargetException(), response,

		writer);

		// return true to prevent any further processing

		return true;

		} catch (Exception e) {

		reportTroubleInGet(e, response, writer);

		// return true to prevent any further processing

		return true;

		}

		}

		}

		}

		

		return false;

		}

		

		/**

		* getRequestPath a returns request path for web service
padded with

		* request.getPathInfo for web services served from
/services directory.

		* This is a required to support serving .jws web
services from /services

		* URL. See AXIS-843 for more information.

		*

		* @param request HttpServletRequest

		* @return String

		*/

		private static String getRequestPath(HttpServletRequest
request) {

		return request.getServletPath() +
((request.getPathInfo() != null) ?

		request.getPathInfo() : "");

		}

		}

		 

________________________________

		From: Jaliya Ekanayake [mailto:jnekanayake@gmail.com] 
		Sent: Monday, July 23, 2007 12:36 PM
		To: Firas Khasawneh (fkhasawn); axis-user@ws.apache.org
		Subject: Re: measuring Axix 1.4 overhead
		
		
		Hi Firas,
		

		The order of  processing in the case of HTTP is;

	
AxisServlet->AxisEngine->HandlerChain->MessageProcessor->Service and
come back.
		 
		If you placed the server in a different machine, then
your RTT should definitely include the network time so it should be
larger than the processing time.
		 
		Thanks,
		-jaliya
		 

			----- Original Message ----- 
			From: Firas Khasawneh (fkhasawn)
<mailto:fkhasawn@cisco.com>  
			To: Jaliya Ekanayake <mailto:jaliya@apache.org>
; axis-dev@ws.apache.org ; axis-user@ws.apache.org 
			Sent: Monday, July 23, 2007 11:27 AM
			Subject: RE: measuring Axix 1.4 overhead

			Hi Jaliya,
			 
			Do you know if response coming back from
transport handler after the request is processed in the Axis engine also
hits AxisServlet and uses doGet?
			 
			Thanks,
			Firas
			
________________________________

			From: Jaliya Ekanayake
[mailto:jnekanayake@gmail.com] 
			Sent: Monday, July 23, 2007 9:42 AM
			To: axis-dev@ws.apache.org;
axis-user@ws.apache.org; Firas Khasawneh (fkhasawn)
			Subject: Re: measuring Axix 1.4 overhead
			
			
			Hi Firas,
			 
			Are you trying both axis server and the client
in a same machine? If you put the handler in transport section, then
what you will measure is the time it takes inside the engine from
transport handlers ->service -> transport handlers. One other
possibility is to keep track of the time in AxisServlet. Measure the
time in AxisServlet before it calls AxisEngine's invoke(..) method and
after it is returned and you will get the time for the total invocation.
			 
			Thanks,
			-jaliya

				----- Original Message ----- 
				From: Firas Khasawneh (fkhasawn)
<mailto:fkhasawn@cisco.com>  
				To: axis-user@ws.apache.org ;
axis-dev@ws.apache.org 
				Sent: Monday, July 23, 2007 6:06 AM
				Subject: RE: measuring Axix 1.4 overhead

				Any help regarding the below please? any
suggestions on how to measure the overhead Axis adds?

________________________________

				From: Firas Khasawneh (fkhasawn) 
				Sent: Sunday, July 22, 2007 11:50 PM
				To: 'axis-user@ws.apache.org'
				Subject: measuring Axix 1.4 overhead
				
				
				
				
				Hi all,
				 
				Anybody knows how to measure the
overhead Axis 1.4 adds to response time? I created a handler in the
requestFlow to  store System.currentTimeMillis in messageContext and
another handler in the responseFlow that retrieved this value and
subtracts it from System.currentTimeMillis(), when I use these classes
in the global conf or transport (server side) I am getting values that
correspond to the response time the client is getting so it looks like
it is not calculating the Axix overhead on the server side, when I put
these handlers in the requestFlow and responseFlow in the service
section in server-conf.wsdd it gives differnt time which seem right but
I am nti sure if this is the Axix engine overhead? Any suggestions?
other ways to do this? please reply back to me or CC me if you are
sending to the list since I am not yet a member in this list.
				 
				Regards,
				Firas Khasawneh


Mime
View raw message