Unfinished deployment in JBoss 7.1.1 on linux
zlazarev256 Nov 15, 2012 11:46 AMHi,
After some porting changes from JBoss 5.1.0 to JBoss 7.1.1 our application worked fine on Windows 7 platform.
When trying to deploy this application on linux machine (both Ubuntu and RedHat, were tried) I encounter an issue
by which deployment enters idle state.
After investigating the issue I realized that a servlet in its init() method is awaiting for the proxy component that
represents my EJB stateless session bean. The code snippets below leads to the 'gate' flag for that component
that on Windows 7 is 'ture' and on linux machine is 'false':
# componentName | CAAdminSessionBean
# componentClass | class org.ejbca.core.ejb.ca.caadmin.CAAdminSessionBean
# org.jboss.as.ejb3.component.stateless.StatelessSessionComponent(org.jboss.as.ee.component.BasicComponent)
protected BasicComponentInstance constructComponentInstance(ManagedReference instance, boolean invokePostConstruct, InterceptorFactoryContext context) {
-> waitForComponentStart();
...
}
protected void waitForComponentStart() {
if (!gate) {
// Block until successful start
synchronized (this) {
if (stopping.get()) {
throw MESSAGES.componentIsStopped();
}
while (!gate) {
// TODO: check for failure condition
try {
-> wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw MESSAGES.componentNotAvailable();
}
}
}
}
}
The stack of JBoss Interceptors is given in reverse order to track back the issue that starts in servlet:
The interesting thing is that the proxy for local interface is created (it is represented by View39),
but the bean itselft is not - this is indicated by gate = false flag.
#
# org.ejbca.core.ejb.ca.caadmin.CAAdminSessionLocal$$$View39
# Proxy for view class: org.ejbca.core.ejb.ca.caadmin.CAAdminSessionLocal of EJB: CAAdminSessionBean
# caAdminSession | org.ejbca.core.ejb.ca.caadmin.CAAdminSessionLocal
#
#
# org.ejbca.ui.web.admin.configuration.StartServiceServlet
public void init(ServletConfig config) throws ServletException {
. . .
-> caAdminSession.initializeAndUpgradeCAs(admin);
. . .
}
# org.jboss.as.ee.component.ProxyInvocationHandler
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
final Interceptor interceptor = interceptors.get(method);
if (interceptor == null) {
throw new NoSuchMethodError(method.toString());
}
final InterceptorContext context = new InterceptorContext();
// special location for original proxy
context.putPrivateData(Object.class, proxy);
context.putPrivateData(Component.class, component);
context.putPrivateData(ComponentView.class, componentView);
context.setParameters(args);
context.setMethod(method);
// setup the public context data
context.setContextData(new HashMap());
-> return interceptor.processInvocation(context);
}
# org.jboss.invocation.ChainedInterceptor
public Object processInvocation(final InterceptorContext context) throws Exception {
final int oldNext = context.getNextInterceptorIndex();
final List<Interceptor> old = context.getInterceptors();
context.setInterceptors(interceptors);
try {
-> return context.proceed();
} finally {
context.setInterceptors(old, oldNext);
}
}
# org.jboss.invocation.InterceptorContext
public Object proceed() throws Exception {
final ListIterator<Interceptor> iterator = interceptorIterator;
if (iterator.hasNext()) {
Interceptor next = iterator.next();
try {
-> return next.processInvocation(this);
} finally {
if (iterator.hasPrevious()) iterator.previous();
}
} else {
throw msg.cannotProceed();
}
}
# org.jboss.as.ee.component.TCCLInterceptor
public Object processInvocation(final InterceptorContext context) throws Exception {
final ClassLoader oldTccl = SecurityActions.getContextClassLoader();
try {
SecurityActions.setContextClassLoader(classLoader);
-> return context.proceed();
} finally {
SecurityActions.setContextClassLoader(oldTccl);
}
}
#
# org.jboss.as.ejb3.tx.CMTTxInterceptor
public Object processInvocation(InterceptorContext invocation) throws Exception {
final EJBComponent component = (EJBComponent) invocation.getPrivateData(Component.class);
final MethodIntf methodIntf = MethodIntfHelper.of(invocation);
final TransactionAttributeType attr = component.getTransactionAttributeType(methodIntf, invocation.getMethod());
final int timeoutInSeconds = component.getTransactionTimeout(methodIntf, invocation.getMethod());
switch (attr) {
case MANDATORY:
return mandatory(invocation, component);
case NEVER:
return never(invocation, component);
case NOT_SUPPORTED:
return notSupported(invocation, component);
case REQUIRED:
-> return required(invocation, component, timeoutInSeconds);
case REQUIRES_NEW:
return requiresNew(invocation, component, timeoutInSeconds);
case SUPPORTS:
return supports(invocation, component);
default:
throw new IllegalStateException("Unexpected tx attribute " + attr + " on " + invocation);
}
}
# org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor
public Object processInvocation(InterceptorContext context) throws Exception {
PooledComponent<ComponentInstance> component = (PooledComponent<ComponentInstance>) getComponent(context, EJBComponent.class);
-> ComponentInstance instance = component.getPool().get();
context.putPrivateData(ComponentInstance.class, instance);
boolean discarded = false;
try {
# StrictMaxPool
public T get() {
. . .
T bean = null;
try {
// Pool is empty, create an instance
-> bean = create();
} finally {
. . .
return bean;
}
# org.jboss.as.ejb3.component.stateless.StatelessSessionComponent
StatelessObjectFactory<StatelessSessionComponentInstance> factory = new StatelessObjectFactory<StatelessSessionComponentInstance>() {
@Override
public StatelessSessionComponentInstance create() {
-> return (StatelessSessionComponentInstance) createInstance();
}
@Override
public void destroy(StatelessSessionComponentInstance obj) {
obj.destroy();
}
};
# componentName | CAAdminSessionBean
# componentClass | class org.ejbca.core.ejb.ca.caadmin.CAAdminSessionBean
# org.jboss.as.ejb3.component.stateless.StatelessSessionComponent(org.jboss.as.ee.component.BasicComponent)
protected BasicComponentInstance constructComponentInstance(ManagedReference instance, boolean invokePostConstruct, InterceptorFactoryContext context) {
-> waitForComponentStart();
...
}
protected void waitForComponentStart() {
if (!gate) {
// Block until successful start
synchronized (this) {
if (stopping.get()) {
throw MESSAGES.componentIsStopped();
}
while (!gate) {
// TODO: check for failure condition
try {
-> wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw MESSAGES.componentNotAvailable();
}
}
}
}
}
The structure of the application ear file is 8 war modules, 2 ejb modules and the library jars under lib entry:
adminweb.war
...
more 7 wars
...
ejbca-ejb.jar
ejbca-ws-ejb.jar
I tried following things:
1. Changed @Stateless(mappedName=__old_jndiName__ to
@Stateless(mappedName=java:global/ejbca/ejbca-ejb/CAAdminSessionBean!org.ejbca.ca.caadmin.CAAdminSessionRemote)
2. Added below entry to standalone.xml to explicitly tie war module with ejb.
<
ear-subdeployments-isolated
>false</
ear-subdeployments-isolated
>
3. Added jboss-deployment-structure.xml file to META-INF of ear file to explicitly tie war module with ejb.
<
jboss-deployment-structure
>
<
sub-deployment
name
=
"adminweb.war"
>
<
dependencies
>
<
module
name
=
"deployment.ejbca.ear.ejbca-ejb.jar"
/>
</
dependencies
>
</
sub-deployment
>
</
jboss-deployment-structure
>
The latter led to unnecessary dependencies errors in the logs.
Please advise.
Thanks.
Zeev