[Design of JCA on JBoss] - CachedConnectionManager and 'late' connection closing
by wolfc
Might I breach the subject of using CachedConnectionManager and JPA again?
Or should I now duck and cover? ;-)
I'm encountering the infamous 'Trying to return an unknown connection2!':
2009-06-11 05:25:32,969 TRACE [org.jboss.resource.connectionmanager.CachedConnectionManager] (http-10.16.43.69-8080-1) registering connection from org.jboss.resource.connectionmanager.TxConnectionManager@31ade61, connection : org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@16a0d419, key: org.apache.geronimo.samples.daytrader.ejb3.TradeSLSBBean@6445ac31
| 2009-06-11 05:25:32,970 TRACE [org.jboss.resource.connectionmanager.CachedConnectionManager] (http-10.16.43.69-8080-1) popped object: org.jboss.resource.connectionmanager.CachedConnectionManager$KeyConnectionAssociation@3e20ce61
| 2009-06-11 05:25:32,972 TRACE [org.jboss.resource.connectionmanager.CachedConnectionManager] (http-10.16.43.69-8080-1) unregistering connection from org.jboss.resource.connectionmanager.TxConnectionManager@31ade61, object: org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@16a0d419, key: org.jboss.web.tomcat.service.jca.CachedConnectionValve@7171e245
| 2009-06-11 05:25:32,972 INFO [org.jboss.resource.connectionmanager.TxConnectionManager] (http-10.16.43.69-8080-1) throwable from unregister connection
| java.lang.IllegalStateException: Trying to return an unknown connection2! org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@16a0d419
As per http://www.jboss.org/community/wiki/WhydoIgetTryingtoreturnanunknownconne... the workaround would be to disable the cached connection interceptors/valves.
But I think it's legit to have activity on an open connection during the first phase of a transaction commit. It might be a waste of a connection to keep it open that long, but there is no way JPA / EJB 3 can determine when people are finished using their entities.
Consider the following scenario:
SLSB A calls SLSB B which returns entity C.
SLSB A then calls a lazy association on entity C.
Thus the connection initially opened by B is used by A.
CachedConnectionManager should take similar scenarios in mind before judging the case as faulty.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4237222#4237222
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4237222
16 years, 10 months
[Design of EJB 3.0] - Re: Cleaning up Logging
by jaikiran
Its our use of AbstractRealDeployerWithInput< JBossMetaData> which causes the deployment framework to call our deployer multiple times for the same deployment unit. The logic in AbstractRealDeployerWithInput involves looking for attachments of type JBossMetaData in a given unit and call the deployer for each of these attachments:
AbstractRealDeployerWithInput:
| protected <U> void deploy(DeploymentUnit unit, DeploymentVisitor<U> visitor) throws DeploymentException
| {
| if (visitor == null)
| throw new IllegalArgumentException("Null visitor.");
|
| List<U> visited = new ArrayList<U>();
| try
| {
| Set<? extends U> deployments = unit.getAllMetaData(visitor.getVisitorType());
| for (U deployment : deployments)
| {
| visitor.deploy(unit, deployment);
|
AbstractDeploymentUnit:
| public <T> Set<? extends T> getAllMetaData(Class<T> type)
| {
| if (type == null)
| throw new IllegalArgumentException("Null type");
|
| Set<T> result = new HashSet<T>();
| Map<String, Object> attachments = getAttachments();
| for (Object object : attachments.values())
| {
| if (type.isInstance(object))
| {
| T t = type.cast(object);
| result.add(t);
| }
| }
| if (result.isEmpty() == false)
| deploymentContext.deployed();
| return result;
| }
|
A deployment unit can have multiple attachments of the same type (with different keys) in a given unit and hence the deployer will end up being called that many times.
Looking at the Ejb3DependenciesDeployer, all we are doing is adding a dependency on the "unit" at PRE_REAL stage. So i guess we can change the deployer as follows:
1) Change the deployer to extend from AbstractDeployer
2) Set the stage of the deployer as PRE_REAL (this is already there in the current deployer)
3) setInput(JBossMetaData.class) so that the deployer expects a JBossMetaData as a requirement
4) addInput(MergedJBossMetaDataDeployer.EJB_MERGED_ATTACHMENT_NAME) so that the deployer gets called at the right time (when the metadata has been merged)
Here's the change:
|
| Index: src/main/org/jboss/ejb3/deployers/Ejb3DependenciesDeployer.java
| ===================================================================
| --- src/main/org/jboss/ejb3/deployers/Ejb3DependenciesDeployer.java (revision 90046)
| +++ src/main/org/jboss/ejb3/deployers/Ejb3DependenciesDeployer.java (working copy)
| @@ -27,66 +27,60 @@
| import org.jboss.dependency.spi.ControllerState;
| import org.jboss.deployers.spi.DeploymentException;
| import org.jboss.deployers.spi.deployer.DeploymentStages;
| -import org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployerWithInput;
| -import org.jboss.deployers.spi.deployer.helpers.DeploymentVisitor;
| +import org.jboss.deployers.spi.deployer.helpers.AbstractDeployer;
| import org.jboss.deployers.structure.spi.DeploymentUnit;
| import org.jboss.deployers.vfs.plugins.dependency.DependenciesMetaData;
| -import org.jboss.deployers.vfs.plugins.dependency.DependencyItemMetaData;
| +import org.jboss.ejb.deployers.MergedJBossMetaDataDeployer;
| import org.jboss.metadata.ejb.jboss.JBossMetaData;
|
| /**
| * @author <a href="mailto:cdewolf@redhat.com">Carlo de Wolf</a>
| * @version $Revision$
| */
| -public class Ejb3DependenciesDeployer extends AbstractRealDeployerWithInput<JBossMetaData>
| +public class Ejb3DependenciesDeployer extends AbstractDeployer
| {
| + /**
| + * Constructor
| + */
| public Ejb3DependenciesDeployer()
| {
| + // PRE_REAL stage is when we run
| setStage(DeploymentStages.PRE_REAL);
| + // we need JBossMetadata as input
| + setInput(JBossMetaData.class);
| + // we should run after the metadata has been merged
| + addInput(MergedJBossMetaDataDeployer.EJB_MERGED_ATTACHMENT_NAME);
| + // this is our output
| setOutput(DependenciesMetaData.class);
| - DeploymentVisitor<JBossMetaData> visitor = new DeploymentVisitor<JBossMetaData>()
| - {
| - public void deploy(DeploymentUnit unit, JBossMetaData deployment) throws DeploymentException
| - {
| - log.info("Encountered deployment " + unit);
| -
| - if(!deployment.isEJB3x())
| - return;
| -
| - // TODO: get the dependencies from beans.xml
| - /*
| - DependenciesMetaData dependencies = new DependenciesMetaData();
| - List<DependencyItemMetaData> items = new ArrayList<DependencyItemMetaData>();
| - items.add(createDependencyItemMetaData(TransactionManager.class.getName()));
| - dependencies.setItems(items);
| - log.debug("Encountered EJB3 deployment " + unit + ", adding dependencies " + items);
| - // We add to toplevel, because DeploymentControllerContext will deploy all kids when it goes to install
| - unit.getTopLevel().addAttachment(DependenciesMetaData.class, dependencies);
| - */
| - //ControllerContext context = unit.getAttachment(ControllerContext.class);
| - unit.addIDependOn(new AbstractDependencyItem(unit.getName(), TransactionManager.class, new ControllerState("Real"), ControllerState.INSTALLED));
| - }
| + }
|
| - private DependencyItemMetaData createDependencyItemMetaData(String name)
| - {
| - DependencyItemMetaData item = new DependencyItemMetaData();
| - item.setValue(name);
| - // This is ugly, MC checks on String value
| - //item.setWhenRequired(new ControllerState(DeploymentStages.REAL.toString()));
| - item.setWhenRequired(new ControllerState("Real"));
| - item.setDependentState(ControllerState.INSTALLED);
| - return item;
| - }
| + /**
| + * Adds a dependency on {@link TransactionManager} class to the <code>unit</code>
| + * if the deployment unit contains a EJB3 deployment.
| + *
| + * @param unit The unit being deployed
| + */
| + public void deploy(DeploymentUnit unit) throws DeploymentException
| + {
| + JBossMetaData metadata = unit.getAttachment(JBossMetaData.class);
|
| - public Class<JBossMetaData> getVisitorType()
| - {
| - return JBossMetaData.class;
| - }
| + // we have marked this deployer as requiring the JBossMetaData input,
| + // so if it's not present then its an issue with MC deployers framework, hence
| + // the assert instead of an exception
| + assert metadata != null : "Unit " + unit + " does not have " + JBossMetaData.class + " as attachment";
|
| - public void undeploy(DeploymentUnit unit, JBossMetaData deployment)
| - {
| - }
| - };
| - setDeploymentVisitor(visitor);
| + // we are only interested in EJB3 deployments
| + if (!metadata.isEJB3x())
| + {
| + return;
| + }
| + if (log.isTraceEnabled())
| + {
| + log.trace("Adding " + TransactionManager.class + " as a dependency on unit " + unit);
| + }
| + // add a dependency on the unit
| + unit.addIDependOn(new AbstractDependencyItem(unit.getName(), TransactionManager.class,
| + new ControllerState("Real"), ControllerState.INSTALLED));
| +
| }
| }
|
Thoughts?
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4237186#4237186
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4237186
16 years, 10 months