Hey folks

I have been digging into our support for connectors in WARs and EARs, and I
believe I have uncovered (and hopefully patched) a few issues, relating to
EAR deployments, and defining containers in an application's resources.xml
file. I have 2 PRs (which are not ready to be merged yet), and both have a
sample with a connector in a WAR and a connector in a EAR file.

In essence, the issue that I have run into, is where the resource adapter
and container are defined in an application's resources.xml, like this:

<resources>
    <Resource id="SampleResourceAdapter" class-name="org.superbiz.
connector.adapter.SampleResourceAdapter">
    </Resource>

    <Container id="SampleMDBContainer" ctype="MESSAGE">
        ResourceAdapter=SampleResourceAdapter
        ActivationSpecClass=org.superbiz.connector.adapter.
SampleActivationSpec
        MessageListenerInterface=org.superbiz.connector.api.InboundListener
    </Container>

    <Resource id="SampleConnectionFactory"
type="org.superbiz.connector.api.SampleConnectionFactory"
class-name="org.superbiz.connector.adapter.SampleManagedConnectionFactory">
        ResourceAdapter=SampleResourceAdapter
        TransactionSupport=none
    </Resource>
</resources>

when that application is deployed through webapps, either as an EAR or a
WAR, it would fail:

at org.apache.openejb.assembler.classic.Assembler.
replaceResourceAdapterProperty(Assembler.java:2680)
at org.apache.openejb.assembler.classic.Assembler.createContainer(Assembler.
java:2550)
at org.apache.openejb.config.ConfigurationFactory.install(
ConfigurationFactory.java:429)
at org.apache.openejb.config.AutoConfig.processApplicationContainers(
AutoConfig.java:906)
at org.apache.openejb.config.AutoConfig.deploy(AutoConfig.java:191)
at org.apache.openejb.config.ConfigurationFactory$Chain.
deploy(ConfigurationFactory.java:403)
at org.apache.openejb.config.ConfigurationFactory.configureApplication(
ConfigurationFactory.java:971)

In essence what was happening was, the resource for SampleResourceAdapter
was being created as a lazy resource (i.e. initialized on first lookup),
and the creation of the container (which happened with TCCL being set to
the main TomEE classloader), triggered that lookup, which failed with a
class not found exception. When the EAR file was deployed under apps/ the
deployment path is different as these were deployed as part of the
container info, with the right classloader - the difference being the
availability of 'sys' in this method in ConfigurationFactory:

    protected void install(final ContainerInfo serviceInfo) throws
OpenEJBException {
        if (sys != null) {
            sys.containerSystem.containers.add(serviceInfo);
        } else if (!offline) {
            final Assembler assembler = SystemInstance.get().
getComponent(Assembler.class);
            if (assembler != null) {
                assembler.createContainer(serviceInfo);
            }else{
                throw new OpenEJBException("ContainerInfo: Assembler has
not been defined");
            }
        }
    }

When 'sys' is null, TomEE attempts to deploy the container rightaway - the
root of this is in AutoConfig, before AppInfo has been fully constructed. I
have attempted to work around this by setting the right classloaders on
TCCL at the right time. Hopefully, my changes don't look too bad, but I'd
welcome any feedback. I have one remaining problem (unless any more appear)
- in my EAR example (which only seems to work from IntelliJ right now), the
CDI injection of my @ApplicationScoped CDI bean into my MDB fails. Looking
at the BeanManager in the debugger, sure enough, the MessagesReceived bean
is not there. Deploying as a WAR seems ok. I will keep debugging, but if
anyone has any thoughts off the top of their heads, that would be awesome.
Even just a pointer to "here's where we pick up the CDI beans" so I can see
if its an ordering thing would be perfect.

My PRs are here:

https://github.com/apache/tomee/pull/112 [Master]
https://github.com/apache/tomee/pull/113 [1.7.x]

Cheers

Jon

Reply via email to