Skip to content

Commit

Permalink
BZ-1067418 - Class loader problems using remote client
Browse files Browse the repository at this point in the history
(cherry picked from commit 0359c14)
  • Loading branch information
mswiderski committed Mar 3, 2014
1 parent b080a54 commit f3840aa
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 39 deletions.
@@ -0,0 +1,153 @@
package org.kie.services.remote.rest.jaxb;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Validator;

import org.jbpm.kie.services.impl.event.DeploymentEvent;
import org.jbpm.kie.services.impl.event.Undeploy;
import org.kie.services.client.serialization.JaxbSerializationProvider;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsRequest;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsResponse;
import org.kie.services.remote.cdi.DeploymentInfoBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ApplicationScoped
public class DynamicJAXBContext extends JAXBContext {

private static final Logger logger = LoggerFactory.getLogger(DynamicJAXBContext.class);

private Set<Class<?>> types = new CopyOnWriteArraySet<Class<?>>();
private ConcurrentHashMap<String, JAXBContext> contexts = new ConcurrentHashMap<String, JAXBContext>();

@Inject
private DeploymentInfoBean deploymentClassNameBean;

private UriInfo uriInfo;


public DynamicJAXBContext() {
types.add(JaxbCommandsRequest.class);
types.add(JaxbCommandsResponse.class);
}

@Override
public Unmarshaller createUnmarshaller() throws JAXBException {
JAXBContext context = getContext();
if (context != null) {
return context.createUnmarshaller();
}
return null;
}

@Override
public Marshaller createMarshaller() throws JAXBException {
JAXBContext context = getContext();
if (context != null) {
return context.createMarshaller();
}
return null;
}

@Override
public Validator createValidator() throws JAXBException {
JAXBContext context = getContext();
if (context != null) {
return context.createValidator();
}
return null;
}

public void addType(Class<?> type) {
this.types.add(type);
}

public JAXBContext getContext() {

String deploymentId = getDeploymentId();

if (deploymentId == null) {
logger.error("Unable to find deployment id which results in returning empty JAXBContext");
try {
return JAXBContext.newInstance();
} catch (JAXBException e) {
logger.error( "Unable to create new " + JAXBContext.class.getSimpleName() + " instance.", e);
return null;
}
}

synchronized (contexts) {
// if there is already created context return it
if (contexts.containsKey(deploymentId)) {
return contexts.get(deploymentId);
}

Set<Class<?>> classesForSerialization = new HashSet<Class<?>>();
classesForSerialization.addAll(JaxbSerializationProvider.PRIMITIVE_ARRAY_CLASS_SET);

if( deploymentId != null ) {
// retrieve class list from kjar
Collection<Class<?>> deploymentClassNames = deploymentClassNameBean.getDeploymentClasses(deploymentId);
for( Class<?> clazz : deploymentClassNames ) {
logger.debug( "Adding {} to JAXBContext instance.", clazz.getName() );
}
classesForSerialization.addAll(deploymentClassNames);
}

// Add given types to list
classesForSerialization.addAll(types);

// Create JAXBContext instance and return it.
Class<?> [] types = classesForSerialization.toArray(new Class[classesForSerialization.size()]);

try {
JAXBContext context = JAXBContext.newInstance(types);
contexts.put(deploymentId, context);

return context;
} catch (JAXBException jaxbe) {
logger.error( "Unable to create new " + JAXBContext.class.getSimpleName() + " instance.", jaxbe);
}
}

return null;
}

public void removeOnUnDeploy(@Observes @Undeploy DeploymentEvent event) {
contexts.remove(event.getDeploymentId());
}

protected String getDeploymentId() {
String deploymentId = null;
List<String> deploymentIdParams = uriInfo.getPathParameters().get("deploymentId");
if( deploymentIdParams != null && ! deploymentIdParams.isEmpty() ) {
deploymentId = deploymentIdParams.get(0);
} else {
deploymentIdParams = uriInfo.getQueryParameters().get("deploymentId");
if( deploymentIdParams != null && ! deploymentIdParams.isEmpty() ) {
deploymentId = deploymentIdParams.get(0);
}
}

return deploymentId;
}


public void setUriInfo(UriInfo uriInfo) {
this.uriInfo = uriInfo;
}

}
Expand Up @@ -30,50 +30,17 @@ public class JaxbContextResolver implements ContextResolver<JAXBContext> {
private static final Logger logger = LoggerFactory.getLogger(JaxbContextResolver.class);

@Inject
private DeploymentInfoBean deploymentClassNameBean;
private DynamicJAXBContext dynamicContext;

@Context
private UriInfo uriInfo;

@Override
public JAXBContext getContext(Class<?> type) {
logger.debug( "Resolving JAXBContext for " + type.getName() + " instance in input.");
String deploymentId = null;
List<String> deploymentIdParams = uriInfo.getPathParameters().get("deploymentId");
if( deploymentIdParams != null && ! deploymentIdParams.isEmpty() ) {
deploymentId = deploymentIdParams.get(0);
} else {
deploymentIdParams = uriInfo.getQueryParameters().get("deploymentId");
}
if( deploymentIdParams != null && ! deploymentIdParams.isEmpty() ) {
deploymentId = deploymentIdParams.get(0);
}

Set<Class<?>> classesForSerialization = new HashSet<Class<?>>();
classesForSerialization.addAll(JaxbSerializationProvider.PRIMITIVE_ARRAY_CLASS_SET);

if( deploymentId != null ) {
// retrieve class list from kjar
Collection<Class<?>> deploymentClassNames = deploymentClassNameBean.getDeploymentClasses(deploymentId);
for( Class<?> clazz : deploymentClassNames ) {
logger.debug( "Adding {} to JAXBContext instance.", clazz.getName() );
}
classesForSerialization.addAll(deploymentClassNames);
}

// Add given type to list
classesForSerialization.add(type);

// Create JAXBContext instance and return it.
Class<?> [] types = classesForSerialization.toArray(new Class[classesForSerialization.size()]);

try {
return JAXBContext.newInstance(types);
} catch (JAXBException jaxbe) {
logger.error( "Unable to create new " + JAXBContext.class.getSimpleName() + " instance.", jaxbe);
}

return null;
dynamicContext.addType(type);
// this assumes that UriInfo is proxied so it will have right values for every request
dynamicContext.setUriInfo(uriInfo);
return dynamicContext;
}

}

0 comments on commit f3840aa

Please sign in to comment.