Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PAYARA-1072 PAYARA-1740 Refactor context util and bug fixes #1700

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ public void initialize() {

// try again

if (ctxUtil.getApplicationName() == null) {
ctxUtil = Globals.getDefaultHabitat().getService(JavaEEContextUtil.class);
if (ctxUtil.getInvocationComponentId() == null) {
ctxUtil.setInstanceContext();
}

if (managedExecutorService == null) {
Expand Down Expand Up @@ -161,8 +161,7 @@ public void eventReceived(final PayaraClusteredCDIEvent event) {
return;
}

Context ctx = ctxUtil.pushContext();
try {
try(Context ctx = ctxUtil.pushContext()) {
managedExecutorService.submit(new Runnable() {
@Override
public void run() {
Expand Down Expand Up @@ -204,8 +203,6 @@ public Class<? extends Annotation> annotationType() {
}
}
});
} finally {
ctxUtil.popContext(ctx);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@
*/
package fish.payara.appserver.context;

import com.sun.enterprise.util.Utility;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.internal.api.JavaEEContextUtil;
import org.jboss.weld.context.bound.BoundRequestContext;

Expand All @@ -53,13 +55,31 @@
class ContextImpl {
@RequiredArgsConstructor
public static class Context implements JavaEEContextUtil.Context {
final ClassLoader classLoader;
final ComponentInvocation invocation;
@Override
public void close() {
if (invocation != null) {
invMgr.postInvoke(invocation);
Utility.setContextClassLoader(oldClassLoader);
}
}

private final ClassLoader oldClassLoader;
private final ComponentInvocation invocation;
private final InvocationManager invMgr;
}

@RequiredArgsConstructor
public static class RequestContext implements JavaEEContextUtil.RequestContext{
final JavaEEContextUtil.Context rootCtx;
public static class RequestContext implements JavaEEContextUtil.Context {
@Override
public void close() {
if (ctx != null) {
ctx.deactivate();
ctx.dissociate(storage);
}
rootCtx.close();
}

private final JavaEEContextUtil.Context rootCtx;
final BoundRequestContext ctx;
final Map<String, Object> storage;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,20 @@
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.JndiNameEnvironment;
import com.sun.enterprise.util.Utility;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import org.glassfish.internal.api.JavaEEContextUtil;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.enterprise.inject.spi.CDI;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.api.ServerContext;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;
import org.jboss.weld.context.bound.BoundRequestContext;
import org.jvnet.hk2.annotations.Service;

Expand All @@ -67,19 +68,24 @@
*/
@Service
@PerLookup
public class JavaEEContextUtilImpl implements JavaEEContextUtil {
public class JavaEEContextUtilImpl implements JavaEEContextUtil, Serializable {
@PostConstruct
void init() {
capturedInvocation = serverContext.getInvocationManager().getCurrentInvocation();
if(capturedInvocation != null) {
capturedInvocation = capturedInvocation.clone();
}
serverContext = Globals.getDefaultHabitat().getService(ServerContext.class);
compEnvMgr = Globals.getDefaultHabitat().getService(ComponentEnvManager.class);

doSetInstanceContext();
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
init();
}

/**
* pushes Java EE invocation context
*
* @return old ClassLoader, or null if no invocation has been created
* @return the new context
*/
@Override
public Context pushContext() {
Expand All @@ -95,16 +101,7 @@ public Context pushContext() {
if(invocationCreated) {
Utility.setContextClassLoader(getInvocationClassLoader());
}
return new ContextImpl.Context(oldClassLoader, invocationCreated? invMgr.getCurrentInvocation() : null);
}

@Override
public void popContext(Context _ctx) {
ContextImpl.Context ctx = (ContextImpl.Context)_ctx;
if (ctx.invocation != null) {
getServerContext().getInvocationManager().postInvoke(ctx.invocation);
Utility.setContextClassLoader(ctx.classLoader);
}
return new ContextImpl.Context(oldClassLoader, invocationCreated? invMgr.getCurrentInvocation() : null, invMgr);
}

/**
Expand All @@ -114,7 +111,7 @@ public void popContext(Context _ctx) {
* @return new context that was created
*/
@Override
public RequestContext pushRequestContext() {
public Context pushRequestContext() {
Context rootCtx = pushContext();
BoundRequestContext brc = CDI.current().select(BoundRequestContext.class).get();
ContextImpl.RequestContext context = new ContextImpl.RequestContext(rootCtx, brc.isActive()? null : brc, new HashMap<String, Object>());
Expand All @@ -126,63 +123,62 @@ public RequestContext pushRequestContext() {
}

/**
* context to pop from the stack
*
* @param context to be popped
* set context class loader by component ID
*/
@Override
public void popRequestContext(RequestContext context) {
ContextImpl.RequestContext ctx = (ContextImpl.RequestContext)context;
if (ctx.ctx!= null) {
ctx.ctx.deactivate();
ctx.ctx.dissociate(ctx.storage);
public void setApplicationClassLoader() {
ClassLoader cl = null;
if(capturedInvocation != null && capturedInvocation.getJNDIEnvironment() != null) {
cl = getClassLoaderForEnvironment((JndiNameEnvironment)capturedInvocation.getJNDIEnvironment());
}
else if(componentId != null) {
cl = getClassLoaderForEnvironment(compEnvMgr.getJndiNameEnvironment(componentId));
}
if(cl != null) {
Utility.setContextClassLoader(cl);
}
popContext(ctx.rootCtx);
}

/**
* @return application name or null if there is no invocation context
*/
@Override
public String getApplicationName() {
ComponentInvocation ci = serverContext.getInvocationManager().getCurrentInvocation();
return ci != null? ci.getModuleName() : null;
public ClassLoader getInvocationClassLoader() {
JndiNameEnvironment componentEnv = compEnvMgr.getCurrentJndiNameEnvironment();
return getClassLoaderForEnvironment(componentEnv);
}

/**
* set context class loader by appName
*
* @param appName
*/
@Override
public void setApplicationContext(String appName) {
if(appName == null) {
return;
}
ApplicationInfo appInfo = appRegistry.get(appName);
public void setInstanceContext() {
componentId = null;
doSetInstanceContext();
}

// try plain non-versioned app first
if(appInfo == null) {
appName = stripVersionSuffix(appName);
appInfo = appRegistry.get(appName);
@Override
public String getInvocationComponentId() {
ComponentInvocation inv = serverContext.getInvocationManager().getCurrentInvocation();
return inv != null? inv.getComponentId() : null;
}

@Override
public JavaEEContextUtil setInstanceComponentId(String componentId) {
this.componentId = componentId;
if(componentId != null) {
createInvocationContext();
}
// for versioned applications, search app registry and strip out the version number
if(appInfo == null) {
for(String regAppName : appRegistry.getAllApplicationNames()) {
if(stripVersionSuffix(regAppName).equals(appName)) {
appInfo = appRegistry.get(regAppName);
break;
}
}
return this;
}

private void doSetInstanceContext() {
capturedInvocation = serverContext.getInvocationManager().getCurrentInvocation();
if(capturedInvocation != null) {
capturedInvocation = capturedInvocation.clone();
componentId = capturedInvocation.getComponentId();
}
if(appInfo != null) {
Utility.setContextClassLoader(appInfo.getAppClassLoader());
else if(componentId != null) {
// deserialized version
createInvocationContext();
}
}

@Override
public ClassLoader getInvocationClassLoader() {
JndiNameEnvironment componentEnv = compEnvMgr.getCurrentJndiNameEnvironment();
private ClassLoader getClassLoaderForEnvironment(JndiNameEnvironment componentEnv) {
if(componentEnv instanceof BundleDescriptor) {
BundleDescriptor bd = (BundleDescriptor)componentEnv;
return bd.getClassLoader();
Expand All @@ -193,14 +189,17 @@ public ClassLoader getInvocationClassLoader() {
return null;
}

private static String stripVersionSuffix(String name) {
int delimiterIndex = name.lastIndexOf(':');
return delimiterIndex != -1? name.substring(0, delimiterIndex) : name;
private void createInvocationContext() {
capturedInvocation = new ComponentInvocation();
capturedInvocation.componentId = componentId;
capturedInvocation.setJNDIEnvironment(compEnvMgr.getJndiNameEnvironment(componentId));
capturedInvocation.setComponentInvocationType(ComponentInvocation.ComponentInvocationType.SERVLET_INVOCATION);
}


private @Inject @Getter(AccessLevel.PACKAGE) ServerContext serverContext;
private ComponentInvocation capturedInvocation;
private @Inject ComponentEnvManager compEnvMgr;
private @Inject ApplicationRegistry appRegistry;
private transient @Getter(AccessLevel.PACKAGE) ServerContext serverContext;
private transient ComponentEnvManager compEnvMgr;
private transient ComponentInvocation capturedInvocation;
private String componentId;
private static final long serialVersionUID = 1L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,14 @@ private static String makeBdaId(String friendlyId, BDAType bdaType, String jarAr
return sb.toString();
}

static String stripApplicationVersion(String appName) {
int idx = appName.lastIndexOf(':');
if (idx < 0) {
return appName;
}
return appName.substring(0, idx);
}

static String stripMavenVersion(String name) {
int suffixIdx = name.lastIndexOf('-');
if(suffixIdx > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ public WeldApplicationContainer load(WeldContainer container, DeploymentContext
archiveName = BeanDeploymentArchiveImpl.stripMavenVersion(archiveName);
}
if(!context.getArchiveHandler().getArchiveType().isEmpty()) {
archiveName = String.format("%s.%s", archiveName, context.getArchiveHandler().getArchiveType());
archiveName = String.format("%s.%s", BeanDeploymentArchiveImpl.stripApplicationVersion(archiveName), context.getArchiveHandler().getArchiveType());
}

DeploymentImpl deploymentImpl = context.getTransientAppMetaData(WELD_DEPLOYMENT, DeploymentImpl.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,51 +49,53 @@
@Contract
public interface JavaEEContextUtil {
/**
* pushes Java EE invocation context
* pushes Java EE invocation context onto the invocation stack
* use Lombok @Cleanup or try-with-resources to pop the context
*
* @return old ClassLoader, or null if no invocation has been created
* @return the new context that was created
*/
Context pushContext();

/**
* pushes invocation context onto the stack
* Also creates Request scope
* use Lombok @Cleanup or try-with-resources to pop the context
*
* @return new context that was created
*/
RequestContext pushRequestContext();
Context pushRequestContext();

/**
* context to pop from the stack
*
* @param ctx to be popped
*/
void popContext(Context ctx);
/**
* context to pop from the stack
*
* @param context to be popped
* set context class loader by internal state of this instance
*/
void popRequestContext(RequestContext context);
void setApplicationClassLoader();

/**
* @return application name or null if there is no invocation context
* Sets the state of this instance from current invocation context
*/
String getApplicationName();
void setInstanceContext();

/**
* set context class loader by appName
* sets component ID for this instance and re-generates the invocation based on it
*
* @param appName
* @param componentId
* @return self for fluent API
*/
void setApplicationContext(String appName);
JavaEEContextUtil setInstanceComponentId(String componentId);

/**
* @return Class Loader that's associated with current invocation
* or null if there is no current invocation
*/
ClassLoader getInvocationClassLoader();
/**
* @return component ID for the current invocation (not this instance), not null
*/
String getInvocationComponentId();

interface Context {};
interface RequestContext {};
interface Context extends Closeable {};
interface Closeable extends AutoCloseable {
@Override
public void close();
}
}
Loading