You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2017/03/01 18:01:31 UTC
tomee git commit: TOMEE-2018 connectionFactoryLookup and
destinationLookup not supported for mdbs
Repository: tomee
Updated Branches:
refs/heads/master 4983a0d45 -> 9fa28a270
TOMEE-2018 connectionFactoryLookup and destinationLookup not supported for mdbs
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/9fa28a27
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/9fa28a27
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/9fa28a27
Branch: refs/heads/master
Commit: 9fa28a270008e8ff717cb6f750683a803f6d72dd
Parents: 4983a0d
Author: rmannibucau <rm...@apache.org>
Authored: Wed Mar 1 19:01:03 2017 +0100
Committer: rmannibucau <rm...@apache.org>
Committed: Wed Mar 1 19:01:03 2017 +0100
----------------------------------------------------------------------
.../org/apache/openejb/config/AutoConfig.java | 12 ++
.../apache/openejb/core/mdb/MdbContainer.java | 2 +
.../activemq/ActiveMQResourceAdapter.java | 74 ++++++++++
.../activemq/TomEEMessageActivationSpec.java | 31 ++++
.../activemq/jms2/cdi/JMS2CDIExtension.java | 28 +++-
.../openejb/util/reflection/Reflections.java | 9 +-
.../META-INF/org.apache.openejb/service-jar.xml | 2 +-
.../apache/openejb/activemq/MDBSpecTest.java | 142 +++++++++++++++++++
8 files changed, 292 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java
index 0653f4d..5639b36 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java
@@ -427,6 +427,10 @@ public class AutoConfig implements DynamicDeployer, JndiConstants {
destination = properties.getProperty("destination");
}
+ if (destination == null) { // EE 7/EJB 3.2
+ destination = properties.getProperty("destinationLookup");
+ }
+
// destination
// String destination = properties.getProperty("destination", properties.getProperty("destinationName"));
if (destination == null) {
@@ -2007,6 +2011,14 @@ public class AutoConfig implements DynamicDeployer, JndiConstants {
return id;
}
+ // app resources
+ if (appResources.appId != null && !appResources.appId.isEmpty() && resourceId.startsWith(appResources.appId + '/')) {
+ id = findResourceId(resourceId.substring(appResources.appId.length() + 1), type, required, appResources);
+ if (id != null) {
+ return id;
+ }
+ }
+
// throw an exception or log an error
final String shortName = toShortName(resourceId);
final String message = "No existing resource found while attempting to Auto-link unmapped resource-ref '" +
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java b/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
index 5223db2..389d228 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
@@ -216,6 +216,8 @@ public class MdbContainer implements RpcContainer {
final Set<String> unusedProperties = new TreeSet<String>(objectRecipe.getUnsetProperties().keySet());
unusedProperties.remove("destination");
unusedProperties.remove("destinationType");
+ unusedProperties.remove("destinationLookup");
+ unusedProperties.remove("connectionFactoryLookup");
unusedProperties.remove("beanClass");
if (!unusedProperties.isEmpty()) {
final String text = "No setter found for the activation spec properties: " + unusedProperties;
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/ActiveMQResourceAdapter.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/ActiveMQResourceAdapter.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/ActiveMQResourceAdapter.java
index 6955035..dde1e2b 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/ActiveMQResourceAdapter.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/ActiveMQResourceAdapter.java
@@ -17,20 +17,33 @@
package org.apache.openejb.resource.activemq;
+import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.ra.ActiveMQConnectionRequestInfo;
+import org.apache.activemq.ra.ActiveMQManagedConnection;
import org.apache.activemq.ra.MessageActivationSpec;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.resource.AutoConnectionTracker;
import org.apache.openejb.resource.activemq.jms2.TomEEConnectionFactory;
+import org.apache.openejb.resource.activemq.jms2.TomEEManagedConnectionProxy;
+import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.Duration;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.URISupport;
import org.apache.openejb.util.URLs;
+import org.apache.openejb.util.reflection.Reflections;
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.naming.NamingException;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapterInternalException;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Iterator;
@@ -189,7 +202,68 @@ public class ActiveMQResourceAdapter extends org.apache.activemq.ra.ActiveMQReso
}
@Override
+ public ActiveMQConnection makeConnection(final MessageActivationSpec activationSpec) throws JMSException {
+ if (TomEEMessageActivationSpec.class.isInstance(activationSpec)) {
+ final TomEEMessageActivationSpec s = TomEEMessageActivationSpec.class.cast(activationSpec);
+ if (s.getConnectionFactoryLookup() != null) {
+ try {
+ final Object lookup = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext()
+ .lookup("openejb:Resource/" + s.getConnectionFactoryLookup());
+ if (!ActiveMQConnectionFactory.class.isInstance(lookup)) {
+ final org.apache.activemq.ra.ActiveMQConnectionFactory connectionFactory = org.apache.activemq.ra.ActiveMQConnectionFactory.class.cast(lookup);
+ Connection connection = connectionFactory.createConnection();
+ if (Proxy.isProxyClass(connection.getClass())) { // not great, we should find a better want without bypassing ra layer
+ final InvocationHandler invocationHandler = Proxy.getInvocationHandler(connection);
+ if (AutoConnectionTracker.ConnectionInvocationHandler.class.isInstance(invocationHandler)) {
+ final Object handle = Reflections.get(invocationHandler, "handle");
+ if (TomEEManagedConnectionProxy.class.isInstance(handle)) {
+ final ActiveMQManagedConnection c = ActiveMQManagedConnection.class.cast(Reflections.get(handle, "connection"));
+ final ActiveMQConnection physicalConnection = ActiveMQConnection.class.cast(Reflections.get(c, "physicalConnection"));
+ final RedeliveryPolicy redeliveryPolicy = activationSpec.redeliveryPolicy();
+ if (redeliveryPolicy != null) {
+ physicalConnection.setRedeliveryPolicy(redeliveryPolicy);
+ }
+ return physicalConnection;
+ }
+ }
+ }
+
+ /*
+ final RedeliveryPolicy redeliveryPolicy = activationSpec.redeliveryPolicy();
+ if (redeliveryPolicy != null) {
+ physicalConnection.setRedeliveryPolicy(redeliveryPolicy);
+ }
+ */
+ return null;
+ }
+ } catch (final ClassCastException cce) {
+ throw new java.lang.IllegalStateException(cce);
+ } catch (final NamingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+ return super.makeConnection(activationSpec);
+ }
+
+ @Override
protected ActiveMQConnectionFactory createConnectionFactory(final ActiveMQConnectionRequestInfo connectionRequestInfo, final MessageActivationSpec activationSpec) {
+ if (TomEEMessageActivationSpec.class.isInstance(activationSpec)) {
+ final TomEEMessageActivationSpec s = TomEEMessageActivationSpec.class.cast(activationSpec);
+ if (s.getConnectionFactoryLookup() != null) {
+ try {
+ final Object lookup = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext()
+ .lookup("openejb:Resource/" + s.getConnectionFactoryLookup());
+ if (ActiveMQConnectionFactory.class.isInstance(lookup)) {
+ return ActiveMQConnectionFactory.class.cast(lookup);
+ }
+ return ActiveMQConnectionFactory.class.cast(lookup); // already handled
+ } catch (final NamingException e) {
+ throw new IllegalArgumentException("");
+ }
+ }
+ }
+
final ActiveMQConnectionFactory factory = new TomEEConnectionFactory();
connectionRequestInfo.configure(factory, activationSpec);
return factory;
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/TomEEMessageActivationSpec.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/TomEEMessageActivationSpec.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/TomEEMessageActivationSpec.java
new file mode 100644
index 0000000..9f30911
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/TomEEMessageActivationSpec.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.resource.activemq;
+
+import org.apache.activemq.ra.ActiveMQActivationSpec;
+
+public class TomEEMessageActivationSpec extends ActiveMQActivationSpec {
+ private String connectionFactoryLookup;
+
+ public String getConnectionFactoryLookup() {
+ return connectionFactoryLookup;
+ }
+
+ public void setConnectionFactoryLookup(final String connectionFactoryLookup) {
+ this.connectionFactoryLookup = connectionFactoryLookup;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/jms2/cdi/JMS2CDIExtension.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/jms2/cdi/JMS2CDIExtension.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/jms2/cdi/JMS2CDIExtension.java
index a8aef08..98ef326 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/jms2/cdi/JMS2CDIExtension.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/jms2/cdi/JMS2CDIExtension.java
@@ -86,7 +86,7 @@ public class JMS2CDIExtension implements Extension {
final JMSPasswordCredential credential = annotated.getAnnotation(JMSPasswordCredential.class);
final String jndi = "openejb:Resource/" +
- (jmsConnectionFactory == null ? findAnyConnectionFactory() : jmsConnectionFactory.value());
+ (jmsConnectionFactory == null ? findAnyConnectionFactory() : findMatchingConnectionFactory(jmsConnectionFactory.value()));
return new Key(
jndi,
credential != null ? credential.userName() : null,
@@ -94,6 +94,32 @@ public class JMS2CDIExtension implements Extension {
sessionMode != null ? sessionMode.value() : null);
}
+ private String findMatchingConnectionFactory(final String value) {
+ final OpenEjbConfiguration component = SystemInstance.get().getComponent(OpenEjbConfiguration.class);
+ if (component != null && component.facilities != null) {
+ for (final ResourceInfo ri : component.facilities.resources) {
+ if (!ri.types.contains("javax.jms.ConnectionFactory")) {
+ continue;
+ }
+ if (ri.id.equals(value)) {
+ return ri.id;
+ }
+ }
+ // try application ones
+ for (final ResourceInfo ri : component.facilities.resources) {
+ if (!ri.types.contains("javax.jms.ConnectionFactory")) {
+ continue;
+ }
+ if (ri.id.endsWith(value)) {
+ return ri.id;
+ }
+ }
+ }
+ // something is wrong, just fail
+ throw new IllegalArgumentException(
+ "No connection factory found, either use @JMSConnectionFactory JMSContext or define a connection factory");
+ }
+
private String findAnyConnectionFactory() {
final OpenEjbConfiguration component = SystemInstance.get().getComponent(OpenEjbConfiguration.class);
if (component != null && component.facilities != null) {
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/java/org/apache/openejb/util/reflection/Reflections.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/util/reflection/Reflections.java b/container/openejb-core/src/main/java/org/apache/openejb/util/reflection/Reflections.java
index 250749b..1d0d065 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/util/reflection/Reflections.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/util/reflection/Reflections.java
@@ -108,13 +108,10 @@ public final class Reflections {
while (clazz != null) {
try {
final Field f = clazz.getDeclaredField(field);
- final boolean acc = f.isAccessible();
- f.setAccessible(true);
- try {
- return f.get(instance);
- } finally {
- f.setAccessible(acc);
+ if (!f.isAccessible()) {
+ f.setAccessible(true);
}
+ return f.get(instance);
} catch (final NoSuchFieldException nsfe) {
// no-op
} catch (final Exception e) {
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
index 1df40e3..36eb8e0 100644
--- a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
+++ b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
@@ -482,7 +482,7 @@
# Specifies the activation spec class
- ActivationSpecClass org.apache.activemq.ra.ActiveMQActivationSpec
+ ActivationSpecClass org.apache.openejb.resource.activemq.TomEEMessageActivationSpec
# Specifies the maximum number of bean instances that are
# allowed to exist for each MDB deployment.
http://git-wip-us.apache.org/repos/asf/tomee/blob/9fa28a27/container/openejb-core/src/test/java/org/apache/openejb/activemq/MDBSpecTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/activemq/MDBSpecTest.java b/container/openejb-core/src/test/java/org/apache/openejb/activemq/MDBSpecTest.java
new file mode 100644
index 0000000..c0d7876
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/activemq/MDBSpecTest.java
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.activemq;
+
+import org.apache.activemq.ra.ActiveMQConnectionRequestInfo;
+import org.apache.activemq.ra.MessageActivationSpec;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.resource.activemq.ActiveMQResourceAdapter;
+import org.apache.openejb.resource.activemq.TomEEMessageActivationSpec;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.Configuration;
+import org.apache.openejb.testing.SimpleLog;
+import org.apache.openejb.testng.PropertiesBuilder;
+import org.apache.openejb.util.reflection.Reflections;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Resource;
+import javax.ejb.ActivationConfigProperty;
+import javax.ejb.MessageDriven;
+import javax.inject.Inject;
+import javax.jms.JMSConnectionFactory;
+import javax.jms.JMSConnectionFactoryDefinition;
+import javax.jms.JMSContext;
+import javax.jms.JMSDestinationDefinition;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.Queue;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertTrue;
+
+@SimpleLog
+@RunWith(ApplicationComposer.class)
+@Classes(cdi = true, innerClassesAsBean = true)
+public class MDBSpecTest {
+ @Configuration
+ public Properties config() {
+ return new PropertiesBuilder()
+ // .p("openejb.offline", "true") // helpful in dev but not working cause of dynamic resources
+
+ .p("amq", "new://Resource?type=ActiveMQResourceAdapter")
+ .p("amq.DataSource", "")
+ .p("amq.BrokerXmlConfig", "broker:(vm://localhost)")
+
+ .p("mdbs", "new://Container?type=MESSAGE")
+ .p("mdbs.ResourceAdapter", "amq")
+
+ .p("testcontainer", "new://Container?type=MANAGED")
+
+ .build();
+ }
+
+ @Resource(name = "amq")
+ private ActiveMQResourceAdapter amq;
+
+ @Resource(name = "jms/input")
+ private Queue destination;
+
+ @Inject
+ @JMSConnectionFactory("jms/ConnectionFactory")
+ private JMSContext context;
+
+ @Before
+ public void resetLatch() {
+ Listener.reset();
+ }
+
+ @Test
+ public void checkConfig() throws InterruptedException {
+ // first it works in term of communication
+ context.createProducer().send(destination, "hello");
+ assertTrue(Listener.sync());
+
+ // then we should check we don't create a connection factory but use the config one
+ // Note: if you have time use a custom connection factory to have a better tracking, for now it should be good enough otherwise
+ }
+
+ private Object createFactory(final ActiveMQResourceAdapter amq) {
+ return Reflections.invokeByReflection(
+ amq,
+ "createConnectionFactory",
+ new Class<?>[]{ActiveMQConnectionRequestInfo.class, MessageActivationSpec.class},
+ new Object[]{null, new TomEEMessageActivationSpec() {{
+ setConnectionFactoryLookup("jms/XAConnectionFactory");
+ }}});
+ }
+
+ @JMSDestinationDefinition(name = "jms/input", destinationName = "jms/input", interfaceName = "javax.jms.Queue")
+ @JMSConnectionFactoryDefinition(name = "jms/ConnectionFactory", transactional = false)
+ @MessageDriven(activationConfig = {
+ @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
+ @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/input"),
+ @ActivationConfigProperty(propertyName = "connectionFactoryLookup", propertyValue = "jms/ConnectionFactory")
+ })
+ public static class Listener implements MessageListener {
+ public static volatile CountDownLatch latch;
+ public static volatile boolean ok = false;
+
+ @Override
+ public void onMessage(final Message message) {
+ try {
+ try {
+ final String body = message.getBody(String.class);
+ ok = "hello".equals(body);
+ } catch (final JMSException e) {
+ // no-op
+ }
+ } finally {
+ latch.countDown();
+ }
+ }
+
+ public static void reset() {
+ latch = new CountDownLatch(1);
+ ok = false;
+ }
+
+ public static boolean sync() throws InterruptedException {
+ latch.await(1, TimeUnit.MINUTES);
+ return ok;
+ }
+ }
+}