The topic is old but I have encountered the same issue. Unfortunately existing answers provide no solution.
When you create a Resource
specifying an instance of the DataSource
, Jetty will not provide this instance when JNDI resource is requested. Instead constructor of Resource
makes an attempt to transform the instance to some kind of "recipe" (javax.naming.Reference
to be precise) that tells how to build the new instance of configuration with exact same internals.
It works well in case of basic classes but fails to recreate complex data structures (it failed with List<String>
in my case). So you end up not getting:
- the exact same instance (as you expect of a singleton)
- the exact equivalent of the instance (as you expect of properly working JNDI)
I have implemented a wrapper that allows providing the instance specified when creating the Resource
.
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
public class ExistingInstanceReference extends Reference implements ObjectFactory {
private Object instance;
private static final long serialVersionUID = -2718709718400909747L;
public ExistingInstanceReference() {
super(null);
}
public ExistingInstanceReference(Object instance) {
super(instance.getClass().getName(), ExistingInstanceReference.class.getName(), null);
this.instance = instance;
}
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
if (obj == null) {
return null;
}
ExistingInstanceReference reference = (ExistingInstanceReference) obj;
return reference.instance;
}
}
Note that this implementation fails to comply with Serializable
interface as instance
variable may contain non-serializable object.
Usage:
Resource r = new Resource(webAppContext, "jdbc/testDS", new ExistingInstanceReference(createDataSource()));
Please, consider this solution as a workaround because the real issue is still to be fixed somewhere in Jetty's sources. Unfortunately I have no time to trace this misbehavior to the root.
In addition, I had to set webAppContext.setParentLoaderPriority(true)
because the webapp's classloader didn't see ExistingInstanceReference
class in my setup.