Tudo começou quando ao subir nossa aplicação, que utiliza o js.jar do Rhino, para o weblogic, começamos a obter a seguinte exceção.
java.lang.NoSuchMethodError: org.mozilla.javascript.Context.initStandardObjects()Lorg/mozilla/javascript/ScriptableObject;
O Phillip Calçado, líder de nossa equipe, me deu uma ótima sugestão. Criar um Class Loader para carregar as classes do jar contido em nossa aplicação. Para fazer isso, extendi a classe URLClassLoader e implementei o método loadClass(String). Veja como ficou o código:
public class RhinoClassLoader extends URLClassLoader {
private static final String PREFIXO_JAVASCRIPT = "org.mozilla.javascript.";
private static final String PREFIXO_CLASSFILE = "org.mozilla.classfile.";
private Map classesCarregadas;
public RhinoClassLoader(URL url) {
super(new URL[]{ url }, RhinoClassLoader.class.getClassLoader() );
classesCarregadas = new HashMap();
}
public Class loadClass(String name) throws ClassNotFoundException {
if( name!=null && ( name.indexOf(PREFIXO_JAVASCRIPT)!=-1 || name.indexOf(PREFIXO_CLASSFILE)!=-1 ) ) {
Object classeCarregada = classesCarregadas.get(name);
if( classeCarregada != null ) {
return (Class) classeCarregada;
}
Class classe = findClass(name);
classesCarregadas.put(name, classe);
return classe;
}
return super.loadClass(name);
}
}
Outra coisa importante do código é o cache de classes anteriormente carregadas. Ele é extremamente necessário, senão pode ocorrer um erro indicando que duas classes com o mesmo nome foram carregadas.
Para obter então a classe correta do Rhino, basta utilizar o método forName da classe Class para recebê-la. Veja abaixo como ficaria:
URL url = new URL( "file:///path/para/o/WEB-INF/lib/js.jar" );
RhinoClassLoader loader = new RhinoClassLoader( url );
Class classeContext = Class.forName("org.mozilla.javascript.Context",true,loader);
Context contexto = (Context)classeContext.newInstance();
Object contexto = (Object)classeContext.newInstance();
Method metodoDebug = classeContext.getMethod("isGeneratingDebug",null);
Boolean gerandoDebug = (Boolean) metodoDebug.invoke( contexto, null );
Esse trabalho todo porque o weblogic não sabe brincar. Custava colocar o jar do Rhino separadinho? Tem certas coisas que não dá pra entender. Já falei isso antes, mas repetir nunca é demais. Cada dia que passa mais odeio o weblogic.