OpenNTF/org.openntf.nsfodp

Externally observed LinkageError when compiling a custom renderer in an NSF

Closed this issue · 3 comments

The error is in the format:

2021-11-24T08:56:24.7750152Z [ERROR] Caused by: java.lang.LinkageError: loading constraint violation when overriding method "com/ibm/xsp/renderkit/html_basic/MessagesRendererEx.encodeBegin(Ljavax/faces/context/FacesContext;Ljavax/faces/component/UIComponent;)V" during creation of class "someapp/theme/renderkit/MessagesRenderer": loader "com/ibm/xsp/extlib/javacompiler/JavaSourceClassLoader@29c12712" of class "someapp/theme/renderkit/MessagesRenderer" and loader "java/net/URLClassLoader@f4f6dc2" of class "com/ibm/xsp/renderkit/html_basic/MessagesRendererEx" have different types for the method signature
2021-11-24T10:12:42.0343022Z [INFO] 	at java.lang.ClassLoader.defineClassImpl(Native Method)
2021-11-24T10:12:42.0343723Z [INFO] 	at java.lang.ClassLoader.defineClassInternal(ClassLoader.java:398)
2021-11-24T10:12:42.0344374Z [INFO] 	at java.lang.ClassLoader.defineClass(ClassLoader.java:359)
2021-11-24T10:12:42.0345039Z [INFO] 	at java.lang.ClassLoader.defineClass(ClassLoader.java:314)
2021-11-24T10:12:42.0345765Z [INFO] 	at com.ibm.xsp.extlib.javacompiler.JavaSourceClassLoader.lambda$2(JavaSourceClassLoader.java:161)
2021-11-24T10:12:42.0348037Z [INFO] 	at com.ibm.xsp.extlib.javacompiler.JavaSourceClassLoader$$Lambda$114/0x000000004c9b5910.apply(Unknown Source)
2021-11-24T10:12:42.0367898Z [INFO] 	at java.util.HashMap.computeIfAbsent(HashMap.java:1127)
2021-11-24T10:12:42.0368756Z [INFO] 	at com.ibm.xsp.extlib.javacompiler.JavaSourceClassLoader.findClass(JavaSourceClassLoader.java:150)
2021-11-24T10:12:42.0369517Z [INFO] 	at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:953)
2021-11-24T10:12:42.0370264Z [INFO] 	at java.lang.ClassLoader.loadClass(ClassLoader.java:898)
2021-11-24T10:12:42.0370928Z [INFO] 	at java.lang.ClassLoader.loadClass(ClassLoader.java:881)
2021-11-24T10:12:42.0371777Z [INFO] 	at com.ibm.xsp.extlib.javacompiler.JavaSourceClassLoader.addClasses(JavaSourceClassLoader.java:247)
2021-11-24T10:12:42.0372422Z [INFO] 	... 11 more

This is initially similar to #231 , but that was specifically about overriding a renderer found in your custom OSGi bundle inside the NSF, while this case doesn't have that intermediate level.

So far, I have not been able to reproduce this locally using a couple versions. It was originally observed when compiling in a Docker container using a build of 3.6.0-SNAPSHOT.

This is reproducible locally by also including another class, that one a Converter implementation. I wonder if it's somehow causing trouble by loading XPages core classes from multiple places, or perhaps it's re-loading those classes for each class compilation and considering them different.

There isn't anything about the specific implementations of the classes that causes trouble, and they don't need to be registered in faces-config.xml (which makes sense). The mere presence of these two classes in an NSF will cause this:

package org.openntf.nsfodp.example.nsf;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

public class FileSizeConverter implements Converter {
	@Override public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
		return null;
	}
	@Override public String getAsString(FacesContext context, UIComponent component, Object obj) {
		return null;
	}
}

and

package org.openntf.nsfodp.example.nsf;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import com.ibm.xsp.renderkit.html_basic.MessagesRendererEx;

public class ExampleRenderer extends MessagesRendererEx {
	@Override public void encodeBegin(FacesContext paramFacesContext, UIComponent paramUIComponent) throws IOException {
	}
	@Override public void encodeEnd(FacesContext paramFacesContext, UIComponent paramUIComponent) throws IOException {
	}
}

This turned out to be caused by a problem in the Bazaar upstream: the dependency ClassLoader didn't delegate to the CL passed in to the object, and so it would end up pulling classes from the bundles from a different source.