So then how does one go about fixing these issues? Here are the steps:
- You will need to add the META-INF/Manifest file into the classes directory of your WAR. This will guarantee that the _wl_cls_gen.jar is a valid jar that Struts2 will recognize.
- You will then need to add a struts.xml to your project with the following information:
<constant name="struts.convention.action.includeJars" value=".*_wl_cls_gen.*"/>
Note here that with Struts 2.1, you will be using the struts2-convention plugin, and this is an override for one of the constants that the convention plugin uses to look for actions. - So far, these steps were pretty easy. Now to a little bit of coding work. You will need to change a small piece of code in the convention plugin. There are 2 pieces. One piece is the change in the plugin's struts-plugin.xml. In talking with Musachy Barroso, a lead developer on Struts, this change has already been committed to the trunk. This change is to allow the convention plugin to accept the zip protocol. The change in the struts-plugin.xml is:
<constant name="struts.convention.action.fileProtocols" value="jar,zip" />
The next is the following piece of code in the org.apache.struts2.convention.PackageBasedActionConfigBuilder class:
private SetfileProtocols;
@Inject("struts.convention.action.fileProtocols")
public void setFileProtocols(String fileProtocols) {
if (!StringTools.isTrimmedEmpty(fileProtocols)) {
this.fileProtocols = TextParseUtil.commaDelimitedStringToSet(fileProtocols);
}
}
private UrlSet buildUrlSet() throws IOException {
UrlSet urlSet = new UrlSet(getClassLoader());
urlSet = urlSet.exclude(ClassLoader.getSystemClassLoader().getParent());
urlSet = urlSet.excludeJavaExtDirs();
urlSet = urlSet.excludeJavaEndorsedDirs();
urlSet = urlSet.excludeJavaHome();
urlSet = urlSet.excludePaths(System.getProperty("sun.boot.class.path", ""));
urlSet = urlSet.exclude(".*/JavaVM.framework/.*");
if (includeJars == null) {
urlSet = urlSet.exclude(".*?jar(!/)?");
} else {
//jar urls regexes were specified
ListrawIncludedUrls = urlSet.getUrls();
SetincludeUrls = new HashSet ();
boolean[] patternUsed = new boolean[includeJars.length];
//- Changed section begins
for (URL url : rawIncludedUrls) {
if (fileProtocols.contains(url.getProtocol())) {
//it is a jar file, make sure it macthes at least a url regex
for (int i = 0; i < includeJars.length; i++) {
String includeJar = includeJars[i];
String extUrlForm = url.toExternalForm();
if (Pattern.matches(includeJar, extUrlForm)) {
// If the protocol is zip, convert to jar protocol
if ( extUrlForm.indexOf("zip:")!=-1 ) {
String newUrl = "jar:file:/" +
extUrlForm.substring(4);
url = new URL(newUrl);
}
includeUrls.add(url);
patternUsed[i] = true;
break;
}
}
} else {
//it is not a jar
includeUrls.add(url);
}
}
//- Changed section ends
if (LOG.isWarnEnabled()) {
for (int i = 0; i < patternUsed.length; i++) {
if (!patternUsed[i]) {
LOG.warn("The includeJars pattern [#0] did not match any jars in the classpath", includeJars[i]);
}
}
}
return new UrlSet(includeUrls);
}
return urlSet;
}
The piece of code that hasn't been committed and in talking with Musachy Barroso is felt temporary is the conversion of zip protocol to jar in the buildUrlSet method. This hasn't been committed to the trunk and most likely will go in as a broader code change that will affect the XWork library that Struts2 uses.
What I've laid out are fairly simple changes - compiling the struts2 convention plugin should be a cakewalk (maven based). I will keep this site updated as I hear more from Musachy if you are willing to wait it out before trying Struts2 in Weblogic. Let me know if you have problems getting things to work....
- Amit
UPDATE:
The above changes are not required with Struts 2.2. Just put the following in the struts.properties file of the project.
#struts convention property modifications for Weblogic
struts.convention.action.includeJars=.*?/your-web-app-name.*?jar(!/)?
struts.convention.action.fileProtocols=jar,zip