You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Ivo Grootjes <gr...@chello.nl> on 2004/07/16 01:51:38 UTC

WebLogic hot-deploy causes destroy to be called on ActionServlet

Hi,

 

I'm using weblogic 8.1 sp1 and struts 1.1

 

Since I had a lot of trouble getting hot deploy/swap to work with my struts
1.1 app I did some researching and found that bug #26322 sort of explains
what my problems are, although the provided solution doesn't suffice. The
provided solution RedeployableActionServlet only works around the actual
problem and is only suitable for Tiles users and actually causes
ClassCastExceptions for non Tiles users. 

 

 
/**
 * In development mode, WebLogic 7.0 automatically redeploys servlets by 
creating a new classloader, 
 * then propagates the servlet context to the new servlet classes by 
serializing it. 
 * For some reason unknown to 
 * me, this serialization operation drops the Tiles definitions. The re-
deployed servlets fail
 * with a NPE when looking up any Tiles definition. This basically breaks 
automatic redeployment.
 * <p> 
 * This class works around this issue by detecting when the request
processor 
(which holds the
 * Tiles definitions) was serialized, and re-creating a new instance when
that 
is the case.
 * The Tiles defs are then reloaded as well. This should only happen when
the 
servlet context 
 * was serialized, ie. servlets were redeployed. 
 * 
 * @author Renaud Waldura
 */

 

 

Here is what I found:

 

When weblogic hotdeploys an application the destroy() method of
RequestProcessor gets called. This must be because ActionServlet's destroy()
method gets called. Because the Requestprocessor's destroy() method nulls
out the servlet reference in the Requestprocessor instance,
NullPointerExceptions occur. Thus to prevent this the reference to the
ActionServlet instance in the requestprocessor needs to be restored. This
can be done like this:

 

 

//ActionServlet.java//

------------------------------

    protected synchronized RequestProcessor getRequestProcessor(ModuleConfig
config)

        throws ServletException {

 

        // :FIXME: Document UnavailableException?

 

        RequestProcessor processor = this.getProcessorForModule(config);

 

        if (processor == null) {

            try {

                processor =

                    (RequestProcessor) RequestUtils.applicationInstance(

                        config.getControllerConfig().getProcessorClass());

 

            } catch (Exception e) {

                throw new UnavailableException(

                    "Cannot initialize RequestProcessor of class "

                        + config.getControllerConfig().getProcessorClass()

                        + ": "

                        + e);

            }

 

            processor.init(this, config);

 

            String key = Globals.REQUEST_PROCESSOR_KEY + config.getPrefix();

            getServletContext().setAttribute(key, processor);

 

        }

        

        //if weblogic hotdeployed, we need to set the processor reference to
this actionservlet again

        if ( processor.servlet == null ) {

            processor.servlet = this;

        }

        

        return (processor);

 

    }

 

Although this won't work for the TilesRequestProcessor since the servlet
field in RequestProcessor is marked protected. 

 

What I don't understand is why the servlet reference in RequestProcessor
doesn't get serialized before the destroy method is called. This might be
because the destroy method gets called before the RequestProcessor and
ActionServlet are serialized. I don't have any idea how this works. 

 

A possible but not so pretty solution might be to make the servlet reference
public or make a setter for the servlet reference in RequestProcessor so
that the above solution also works for TilesRequestProcessor. Since I don't
know much (yet) about the internals of the struts core I better let others
decide on this maybe by reopening bug #26322. In anyway the solution
proposed to solve bug #26322 is not enough.

 

Hope this helps,

 

Ivo Grootjes