[SoapRMI] SOLVED: be careful about sharing parser instance [xpp potential cleanup/reset problem]

Aleksander Slominski aslom_at_cs.indiana.edu
Mon, 29 Jul 2002 12:14:50 -0400


"CHEN,SHIH-CHANG (HP-NewJersey,ex2)" wrote:

> > what is the parser state (getEventType()) just before last next()?
>
> 0 (start_document): nost
> 1, 2, 3 or 4: sometime ?

hi,

those constants are defined in interface XmlPullParser - to have more friendly messages use:
* System.out.println(XmlPullParser.TYPES[ parser.getEventType() ]);
* or even better to see actual input and positions
System.out.println(parser.getPositionDescritption());


> > did you make sure that only one thread at any time is accessing
> > parser instance. the easiest approach is to use pool of parser
> > instances that are reused to handle requests (typically each request
> > gets its own parser instance and not shared with other thread).
>
> I also suspect my ide (eclipse) or servlet engine(Tomcat404) has
> threading problems. But a servlet instance is supposed to run in
> one thread. And Servlent container will take care of servlet instance
> pooling. In my case, a parser instance is cached in a servlet instance.
>
> I will using pooling if I cannot solve this problem. Attachment
> is my servlet for server-side. In client-side, I use WebLoad5 to simulate
> concurrent
> 10 http clients.(http://www.radview.com/products/WebLOAD.asp)

i think we have the problem solved  :-)

unless you explicitly make servlet instance thread save
(using marker interface SingleThreadModel) you need to do
your own per-thread initialization outside of init() as this method is called
only once when servlet is created, see:

    http://www.jguru.com/faq/view.jsp?EID=150

(...)Under most circumstances, there is only one instance of your servlet, no matter how
many client requests are in process. That means that at any given moment, there
may be many threads running inside the service() method of your solo instance, all
sharing the same instance data and potentially stepping on each other's toes. This
means that you should be careful to synchronize access to shared data (instance
variables) using the synchronized keyword.(...)

so in your case you _need_ to create new parser instance or use pool
example pool implementation is available at:

   http://www.extreme.indiana.edu/~aslom/xmlpull/org/xmlpull/v1/util/XmlPullParserPool.java

and then your sample can be modified to:

import org.xmlpull.v1.util.XmlPullParserPool;

public class EchoServlet extends HttpServlet {

 //private XmlPullParserFactory pullfactory;
 //reset does not work correctly
 //private XmlPullParser xpp; -- parser instance is NOT multithread safe
  XmlPullParserPool pool;

 public void init() throws ServletException {
  try {
   XmlPullParserFactory pullfactory = XmlPullParserFactory.newInstance();
   pullfactory.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
   pool = new XmlPullParserPool(pullfactory);
  } catch (XmlPullParserException e) {
   e.printStackTrace( System.out );
   throw new ServletException( e.getMessage() );
  }
 }

   public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
    {
     InputStream in = req.getInputStream();
     try {
   pullEcho( in, res.getWriter() );
  } catch (XmlPullParserException e) {
   //e.printStackTrace( System.out );
   throw new IOException( e.getMessage() );
  }//


 private void pullEcho( InputStream in, Writer writer )
        throws IOException,XmlPullParserException
    {
     //XmlPullParser xpp = pullfactory.newPullParser();
     // here access to pool of parser instances
    XmlPullParser xpp = pool.getPullParserFromPool();
    try {
       xpp.setInput ( new InputStreamReader ( in ) );
        int eventType = xpp.getEventType();
    // ...
    // whne finished processing return parser to pool:
      } finally { if(xpp != null) {PullParserPool.return(xpp);} }
    }


let me know if this solved your problem.

thanks,

alek
ps. BTW we are now adding to XmlPull API new interface XmlSerializer
that will make much easier to write echo XML code :-)