To edit or add content to this Wiki, you can simply create a new account at http://wocommunity.org/account.

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Warning
titleWarning

This is legacy information. If you are using Eclipse 3.4 and WOLips 5640 or later, servlet deployment is significantly less complicated, and described in Servlet Deployment Setup.

Introduction

WO developers have been able to deploy their applications as a WAR bundle in a J2EE container since WO 5.1, and as an independent SSDD (Servlet Single Directory Deployment) bundles since WO 5.2. There is some documentation out there already for preparing your apps for this if you use XCode, but more and more developers are ditching that in favor of the vastly superior (in my opinion) Eclipse/WOLips IDE. For more information on XCode, start here. This article is all about how to do things in Eclipse, and then as a bonus, how to create a deploy a project wonder application so that it runs in tomcat. I had a fairly miserable time figuring all of this out, but there's really not that much to it once you have all of the information in one place. Read on...

...

By default, the target tag for ssdd has an attribute that looks like

No Format
'if="${never}"'

. Just delete that, so that the target will execute next time you do an ant install.

...

Now you need to modify your build path to include the framework that lets your webobjects application behave in the servlet world: JavaWOJSPServlet. It's in /System/Library/Frameworks. If you don't know how to modify your build path, go read this.

Now open up your build.properties file, which also resides at the root level of your project. If you don't see it, it's probably hidden from view. Open up the Filters window in package explorer (just like you did above to see the build.xml file), and uncheck build.properties (WOLips). Double click the build.properties file to edit it. There will be a line that looks like "webXML = ". Make that line read 'webXML = true' and then save the file.

...

Henrique created a class called ERXServletAdaptor and it is submitted as a pending project wonder patch as we speak (or as I type, as the case may be). I could not get the code in that patch to run as is, so I have changed it just a bit. Here is my version of the class that works for me. Something very similar to this may soon be bundled with project wonder, but for now, you can just toss this class into your project's Sources folder:

No Format
Code Block
java
java
titleERXServletAdaptor.java
 
package er.extensions.jspservlet;

import java.io.InputStream;
import java.lang.reflect.Method;
import
java.util.HashMap;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import
javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;

import org.apache.log4j.Logger;

import com.webobjects.jspservlet.WOServletAdaptor;

import er.extensions.appserver.ERXApplication;

/**
 * This class is just a wrapper around <code>WOServletAdaptor</code>.
 * <code>ERXServletAdaptor</code> must be used to make Wonder applications
 * compliant with WAR deployment.
 * <p>
 * This class is responsible to invoke the
 * {@link ERXApplication#setup(String[])} method before the application
 * initialization.
 * 
 * @see WOServletAdaptor
 * @author <a href="mailto:hprange@moleque.com.br">Henrique Prange</a>
 */
public class ERXServletAdaptor extends WOServletAdaptor {

	/**
	 * Overrides the <code>_appliationInit</code> and invoke the
	 * {@link ERXApplication#setup(String[])} method before the application
	 * initialization.
	 * 
	 * @see WOServletAdaptor#_applicationInit(ServletContext)
	 */
	
	/*
	 * 
	 * @param servletContext
	 *            The servlet context to get the application class
	 * @throws UnavailableException
	 *             If something wrong happens while trying to invoke the
	 *             application setup method.
	 */
	static void invokeApplicationSetupMethod(ServletContext servletContext) throws UnavailableException {
		ClassLoader classLoader = WOServletAdaptor.class.getClassLoader();

		try {
			String applicationClassName = servletContext.getInitParameter("WOApplicationClass");

			if (applicationClassName == null || "".equals(applicationClassName)) {
				throw new UnavailableException("WOApplicationClass must be defined. Verify your web.xml configuration.");
			}

			Class applicationClass = classLoader.loadClass(applicationClassName);

			Method method = applicationClass.getMethod("setup", new Class[] { String[].class });

			method.invoke(null, new Object[] { new String[0] });
		}
		catch (Exception e) {
			e.printStackTrace();

			throw new UnavailableException("Error initializing ERXServletAdaptor: " + e.getMessage());
		}
	}

	public ERXServletAdaptor() throws ServletException {
		super();
	}

	@Override
	public void init() throws ServletException {
		ERXServletAdaptor.invokeApplicationSetupMethod(getServletContext());
		super.init();
	}
	
}

...

That is pretty much the trick, but there is one last catch. Somehow, tomcat has to know to use your version of the ServletAdaptor, and not the WebObjects version that breaks with wonder. The container gets this information from the web.xml file that we saw magically generated for us in dist/JSPHelloWorld/WEB-INF after we ran our ant task. If you go into the dist folder and open up this file, you will see the following near the bottom:

No Formatcode
xml
xml
 
  <!-- The WebObjects Servlet that interfaces between the Servlet container
       world and the WebObjects world. -->
  <servlet>
    <servlet-name>WOServletAdaptor</servlet-name>
    <servlet-class>com.webobjects.jspservlet.WOServletAdaptor</servlet-class>
    <load-on-startup>5</load-on-startup>
  </servlet>

For our little trick to work, we need to change the class to reference our class, so we change it to look like this:

No Formatcode
xml
xml
 
  <!-- The WebObjects Servlet that interfaces between the Servlet container
       world and the WebObjects world. -->
  <servlet>
    <servlet-name>WOServletAdaptor</servlet-name>
    <servlet-class>er.extensions.jspservlet.ERXServletAdaptor</servlet-class>
    <load-on-startup>5</load-on-startup>
  </servlet>

We can just edit the file by hand and save it, but next time we do an install, we're going to blow that change away and then have to remember all this minutia again to figure out what's going on. So I just modified the build.xml file to make the change for us whenever we do an install. Place this at the bottom of the build.woapp target, and next time you do a build, you'll be in business:

No Formatcode
xml
xml
 
		<!-- fix the web.xml file to use a custom Servlet Adaptor that allows for Project Wonder initialization -->

		<replaceregexp 
   	<replaceregexp 			file="${dest.dir}/${project.name}/WEB-INF/web.xml" 
			match="com.webobjects.jspservlet.WOServletAdaptor" 
   			replace="er.extensions.jspservlet.ERXServletAdaptor" 
			byline="true" />

Done and done

...