The next task was Spring support. Having Spring on the application- and plugin classpath will cause classloader problems (you'll get ClassCastExceptions since the Spring classes are loaded from two different classloaders). Another problem is that both your application and pluto requires the ContextLoaderListener and the contextConfigLocation context parameter to be set. Basically, to make this work with just maven-jetty-plugin configuration options would require me to split the configuration options into three separate files; a webdefaults descriptor, web.xml and an override descriptor. This is really starting to look bad...
The ContextLoaderListener problem was solved using a custom, jetty specific, context listener that use the internal jetty context classes to modify the context parameters and ensuring that only one context loader listener instance exists. I then added this listener to the webdefaults file, ensuring it is the very first listener that is executed. Quite brutal, but it works...
Identifying and collecting all the required stylesheets, JSP files, images etc into one jar file was easy. The hard part was how to make them available to the pluto driver, when they always were meant to be a part of the running web application... So all lookups/URLs to files like /pluto.css, /images/controls/edit.png, /WEB-INF/pluto-portal-driver-config.xml, and not to forget, the jsp that acts as the entry point to the portlet container (I've named it /pluto/index.jsp), would have to be served from this jar. Taking inspiration from the Struts 2 FilterDispatcher, serving static resources referenced from URLs to the web application was easy using a servlet filter. But how was I going to "intercept" the lookups to the resources in /WEB-INF? And how can one serve a JSP file from within a JAR file? Looking through the source of the RenderConfigServiceImpl (which loads the /WEB-INF/pluto-portal-driver-config.xml file) and the Jasper JspServlet, it appears that they both look up resources using ServletContext.getResource and ServletContext.getResourceAsStream. If I could intercept these calls and look up the resources from the classpath instead, the problem should be solved. So I wrote a wrapper servlet for the JspServlet, and a wrapper context listener for the PortalStartupListener (which in turn initializes the RenderConfigServiceImpl) that just delegates to the wrapped objects, passing them a wrapped instance of ServletContext that looks up the resources it does not find in /WEB-INF with the ClassLoader.getResource and ClassLoader.getResourceAsStream methods instead. Problem solved!
This left me with two resources; the pluto.tld file and the customized webdefaults descriptor. For the pluto.tld file, I just placed it in the META-INF folder of the jar file, and renamed it to taglib.tld. This is discovered by the servlet container automatically when it is referenced through the correct uri in the jsp files using it. One file left; the webdefaults descriptor. After a lot of trial and error (again...) (I even tried extending the maven-jetty-plugin to add a new configuration option, but this proved fruitless as I discovered that it is not possible to extend a maven 2 plugin...), I could not find a solution. So it remains unsolved until the maven-jetty-plugin is modified to look up a webdefaults descriptor by some other means than just a file path (I'll probably create a JIRA issue for this. Update: JIRA issue created). But still, I'm now left with only one jar file added to the dependency of the application, and one webdefaults file that I add to the application itself (and is easily excluded in the pom). I've also added the dependency to a profile, so it's only active when I specify this profile on the command line. It looks like this:
Update: The maven-jetty-pluto-embedded artifact is available in the Maven 2 repositories.
Of course, you need the maven-pluto-plugin as well, as described in the previous post. Also, note the system property configuration specifying the id of the portlet to run.
I run this setup using the command mvn jetty:run -P pluto-embedded. Now I'm a lot more happy with the solution. Below is a screenshot how this looks running with the Struts 2 sample portlet application (click the image to enlarge):
You can download the jetty-pluto-web-default.xml file and try it yourself. Just put the xml file in your /WEB-INF folder. All feedback is appreciated.