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 2016/06/17 10:40:53 UTC
[1/2] tomee git commit: TOMEE-1846 adding Template API
Repository: tomee
Updated Branches:
refs/heads/master 066da5ed0 -> e386526f1
TOMEE-1846 adding Template API
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/a5d08be1
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/a5d08be1
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/a5d08be1
Branch: refs/heads/master
Commit: a5d08be10d9ea4b20a9179494fbc9ced140e5439
Parents: 066da5e
Author: Romain manni-Bucau <rm...@gmail.com>
Authored: Fri Jun 17 12:24:19 2016 +0200
Committer: Romain manni-Bucau <rm...@gmail.com>
Committed: Fri Jun 17 12:24:19 2016 +0200
----------------------------------------------------------------------
.../apache/openejb/api/resource/Template.java | 29 ++++
.../openejb/config/ConfigurationFactory.java | 132 ++++++++++++-------
.../java/org/apache/openejb/config/Service.java | 2 +
.../openejb/config/sys/AbstractService.java | 10 ++
.../apache/openejb/config/sys/StackHandler.java | 1 +
.../apache/openejb/resource/TemplateTest.java | 63 +++++++++
6 files changed, 189 insertions(+), 48 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
----------------------------------------------------------------------
diff --git a/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java b/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
new file mode 100644
index 0000000..bb56f28
--- /dev/null
+++ b/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
@@ -0,0 +1,29 @@
+/*
+ * 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.api.resource;
+
+/**
+ * Called to setup a service/resource.
+ *
+ * It is called at the very beginning of resource configuration (ie before provider are resolved)
+ * so the resource can be fully configured.
+ *
+ * @param <T> Service or AbstractService or Resource.
+ */
+public interface Template<T> {
+ void configure(T resource);
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
index 99a91b9..e9fd1d1 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
@@ -22,6 +22,7 @@ import org.apache.openejb.OpenEJBException;
import org.apache.openejb.Vendor;
import org.apache.openejb.api.Proxy;
import org.apache.openejb.api.resource.PropertiesResourceProvider;
+import org.apache.openejb.api.resource.Template;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.assembler.classic.BmpEntityContainerInfo;
@@ -790,6 +791,7 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
service.setConstructor(map.remove("constructor"));
service.setFactoryName(map.remove("factory-name"));
service.setPropertiesProvider(map.remove("properties-provider"));
+ service.setTemplate(map.remove("template"));
final String cp = map.remove("classpath");
if (null != cp) {
@@ -1156,30 +1158,23 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
}
}
- final String providerType = getProviderType(service);
-
- final ServiceProvider provider = resolveServiceProvider(service, infoType);
-
- if (provider == null) {
- final List<ServiceProvider> providers = ServiceUtils.getServiceProvidersByServiceType(providerType);
- final StringBuilder sb = new StringBuilder();
- final List<String> types = new ArrayList<String>();
- for (final ServiceProvider p : providers) {
- for (final String type : p.getTypes()) {
- if (types.contains(type)) {
- continue;
- }
- types.add(type);
- sb.append(System.getProperty("line.separator"));
- sb.append(" <").append(p.getService());
- sb.append(" id=\"").append(service.getId()).append('"');
- sb.append(" type=\"").append(type).append("\"/>");
- }
+ {
+ String template = service.getTemplate();
+ if (template == null) {
+ template = SystemInstance.get().getProperty(Template.class.getName());
+ }
+ if (template != null) {
+ template = unaliasPropertiesProvider(template);
+
+ // don't trim them, user wants to handle it himself, let him do it
+ final ObjectRecipe recipe = newObjectRecipe(template);
+ recipe.setProperty("serviceId", service.getId());
+ // note: we can also use reflection if needed to limit the dependency
+ Template.class.cast(recipe.create()).configure(service);
}
- final String noProviderMessage = messages.format("configureService.noProviderForService", providerType, service.getId(), service.getType(), service.getProvider(), sb.toString());
- throw new NoSuchProviderException(noProviderMessage);
}
+ final ServiceProvider provider = getServiceProvider(service, infoType);
if (service.getId() == null) {
service.setId(provider.getId());
}
@@ -1225,39 +1220,33 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
props.putAll(provider.getProperties());
}
- props.putAll(serviceProperties);
- props.putAll(overrides);
-
- // force user properties last
- String propertiesProvider = service.getPropertiesProvider();
- if (propertiesProvider == null) {
- propertiesProvider = SystemInstance.get().getProperty(PropertiesResourceProvider.class.getName());
+ if (serviceProperties != null) {
+ props.putAll(serviceProperties);
}
- if (propertiesProvider != null) {
- propertiesProvider = unaliasPropertiesProvider(propertiesProvider);
-
- // don't trim them, user wants to handle it himself, let him do it
- final ObjectRecipe recipe = new ObjectRecipe(propertiesProvider);
- recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
- recipe.allow(Option.PRIVATE_PROPERTIES);
- recipe.allow(Option.FIELD_INJECTION);
- recipe.allow(Option.NAMED_PARAMETERS);
- recipe.allow(Option.IGNORE_MISSING_PROPERTIES);
- recipe.setFactoryMethod("provides");
- recipe.setProperty("serviceId", service.getId());
- recipe.setProperties(props);
- recipe.setProperty("properties", props); // let user get all config
- final Properties p = Properties.class.cast(recipe.create());
+ props.putAll(overrides);
- props.putAll(p);
+ {// force user properties last
+ String propertiesProvider = service.getPropertiesProvider();
+ if (propertiesProvider == null) {
+ propertiesProvider = SystemInstance.get().getProperty(PropertiesResourceProvider.class.getName());
+ }
+ if (propertiesProvider != null) {
+ propertiesProvider = unaliasPropertiesProvider(propertiesProvider);
+
+ // don't trim them, user wants to handle it himself, let him do it
+ final ObjectRecipe recipe = newObjectRecipe(propertiesProvider);
+ recipe.setFactoryMethod("provides");
+ recipe.setProperty("serviceId", service.getId());
+ recipe.setProperties(props);
+ recipe.setProperty("properties", props); // let user get all config
+ final Properties p = Properties.class.cast(recipe.create());
+
+ props.putAll(p);
+ }
}
props.remove(IGNORE_DEFAULT_VALUES_PROP);
- if (providerType != null && !provider.getService().equals(providerType)) {
- throw new OpenEJBException(messages.format("configureService.wrongProviderType", service.getId(), providerType));
- }
-
final T info;
try {
info = infoType.newInstance();
@@ -1305,6 +1294,49 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
}
}
+ private <T extends ServiceInfo> ServiceProvider getServiceProvider(
+ final org.apache.openejb.config.Service service,
+ final Class<? extends T> infoType) throws OpenEJBException {
+ final String providerType = getProviderType(service);
+
+ final ServiceProvider provider = resolveServiceProvider(service, infoType);
+
+ if (provider == null) {
+ final List<ServiceProvider> providers = ServiceUtils.getServiceProvidersByServiceType(providerType);
+ final StringBuilder sb = new StringBuilder();
+ final List<String> types = new ArrayList<String>();
+ for (final ServiceProvider p : providers) {
+ for (final String type : p.getTypes()) {
+ if (types.contains(type)) {
+ continue;
+ }
+ types.add(type);
+ sb.append(System.getProperty("line.separator"));
+ sb.append(" <").append(p.getService());
+ sb.append(" id=\"").append(service.getId()).append('"');
+ sb.append(" type=\"").append(type).append("\"/>");
+ }
+ }
+ final String noProviderMessage = messages.format("configureService.noProviderForService", providerType, service.getId(), service.getType(), service.getProvider(), sb.toString());
+ throw new NoSuchProviderException(noProviderMessage);
+ }
+
+ if (!provider.getService().equals(providerType)) {
+ throw new OpenEJBException(messages.format("configureService.wrongProviderType", service.getId(), providerType));
+ }
+ return provider;
+ }
+
+ private ObjectRecipe newObjectRecipe(final String template) {
+ final ObjectRecipe recipe = new ObjectRecipe(template);
+ recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
+ recipe.allow(Option.PRIVATE_PROPERTIES);
+ recipe.allow(Option.FIELD_INJECTION);
+ recipe.allow(Option.NAMED_PARAMETERS);
+ recipe.allow(Option.IGNORE_MISSING_PROPERTIES);
+ return recipe;
+ }
+
private static String unaliasPropertiesProvider(final String propertiesProvider) {
switch (propertiesProvider.toLowerCase(Locale.ENGLISH)) {
case "heroku":
@@ -1318,6 +1350,10 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
}
}
+ private static String unaliasTemplate(final String value) {
+ return value;
+ }
+
/**
* Takes a raw unparsed string expected to be in jvm classpath syntax
* and parses it, producing a collection of URIs representing the absolute
http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
index 7ca596d..58d9792 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
@@ -67,4 +67,6 @@ public interface Service {
String getClasspath();
String getPropertiesProvider();
+
+ String getTemplate();
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
index 6181df5..5771632 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
@@ -83,6 +83,8 @@ public abstract class AbstractService implements Service {
@XmlAttribute(name = "properties-provider")
private String propertiesProvider;
+ @XmlAttribute(name = "template")
+ private String template;
protected AbstractService(final String id) {
this(id, null, null);
@@ -227,6 +229,14 @@ public abstract class AbstractService implements Service {
this.classpath = classpath;
}
+ public String getTemplate() {
+ return template;
+ }
+
+ public void setTemplate(final String template) {
+ this.template = template;
+ }
+
@Override
public boolean equals(final Object o) {
if (this == o) {
http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
index 965c2b5..9f14676 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
@@ -224,6 +224,7 @@ public class StackHandler extends DefaultHandler {
service.setJndi(attributes.getValue("jndi"));
service.setPostConstruct(attributes.getValue("post-construct"));
service.setPreDestroy(attributes.getValue("pre-destroy"));
+ service.setTemplate(attributes.getValue("template"));
service.setPropertiesProvider(attributes.getValue("property-provider"));
if (service.getPropertiesProvider() == null) {
service.setPropertiesProvider(attributes.getValue("properties-provider"));
http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
new file mode 100644
index 0000000..9ad1eff
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import org.apache.openejb.api.resource.Template;
+import org.apache.openejb.config.sys.AbstractService;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.Configuration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Resource;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+
+@Classes
+@RunWith(ApplicationComposer.class)
+public class TemplateTest {
+ @Resource(name = "r1")
+ private MyResource r1;
+
+ @Test
+ public void validAliases() {
+ assertEquals("r1", r1.value);
+ }
+
+ @Configuration
+ public Properties config() {
+ final Properties p = new Properties();
+ p.put("r1", "new://Resource?template=org.apache.openejb.resource.TemplateTest$MyTemplate");
+ return p;
+ }
+
+ public static class MyResource {
+ private String value;
+ }
+
+ public static class MyTemplate implements Template<AbstractService> {
+ private String serviceId;
+
+ @Override
+ public void configure(final AbstractService resource) {
+ resource.setClassName(MyResource.class.getName());
+ resource.getProperties().put("value", serviceId);
+ }
+ }
+}
[2/2] tomee git commit: TOMEE-1847 classpath-api config
Posted by rm...@apache.org.
TOMEE-1847 classpath-api config
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/e386526f
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/e386526f
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/e386526f
Branch: refs/heads/master
Commit: e386526f1a1528d18a70f216f5fc1c584ae27873
Parents: a5d08be
Author: Romain manni-Bucau <rm...@gmail.com>
Authored: Fri Jun 17 12:40:30 2016 +0200
Committer: Romain manni-Bucau <rm...@gmail.com>
Committed: Fri Jun 17 12:40:30 2016 +0200
----------------------------------------------------------------------
.../openejb/assembler/classic/Assembler.java | 22 ++++++-
.../openejb/assembler/classic/ServiceInfo.java | 1 +
.../openejb/config/ConfigurationFactory.java | 3 +
.../java/org/apache/openejb/config/Service.java | 2 +
.../openejb/config/sys/AbstractService.java | 17 +++++
.../apache/openejb/config/sys/StackHandler.java | 3 +
.../openejb/resource/ClasspathAPITest.java | 69 ++++++++++++++++++++
7 files changed, 115 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
index d316dac..ff32a27 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
@@ -48,8 +48,8 @@ import org.apache.openejb.assembler.classic.event.AssemblerDestroyed;
import org.apache.openejb.assembler.classic.event.BeforeStartEjbs;
import org.apache.openejb.assembler.classic.event.ContainerSystemPostCreate;
import org.apache.openejb.assembler.classic.event.ContainerSystemPreDestroy;
-import org.apache.openejb.assembler.classic.event.ResourceCreated;
import org.apache.openejb.assembler.classic.event.ResourceBeforeDestroyed;
+import org.apache.openejb.assembler.classic.event.ResourceCreated;
import org.apache.openejb.assembler.classic.util.ServiceInfos;
import org.apache.openejb.assembler.monitoring.JMXContainer;
import org.apache.openejb.async.AsynchronousPool;
@@ -2958,9 +2958,27 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A
throw new OpenEJBException("Unable to create a classloader for " + serviceInfo.id, e);
}
+ if (!customLoader && serviceInfo.classpathAPI != null) {
+ throw new IllegalArgumentException("custom-api provided but not classpath used for " + serviceInfo.id);
+ }
+
Object service = serviceRecipe.create(loader);
if (customLoader) {
- final Collection<Class<?>> apis = new ArrayList<Class<?>>(Arrays.asList(service.getClass().getInterfaces()));
+ final Collection<Class<?>> apis;
+ if (serviceInfo.classpathAPI == null) {
+ apis = new ArrayList<Class<?>>(Arrays.asList(service.getClass().getInterfaces()));
+ } else {
+ final String[] split = serviceInfo.classpathAPI.split(" *, *");
+ apis = new ArrayList<>(split.length);
+ final ClassLoader apiLoader = Thread.currentThread().getContextClassLoader();
+ for (final String fqn : split) {
+ try {
+ apis.add(apiLoader.loadClass(fqn));
+ } catch (final ClassNotFoundException e) {
+ throw new IllegalArgumentException(fqn + " not usable as API for " + serviceInfo.id, e);
+ }
+ }
+ }
if (apis.size() - (apis.contains(Serializable.class) ? 1 : 0) - (apis.contains(Externalizable.class) ? 1 : 0) > 0) {
service = Proxy.newProxyInstance(loader, apis.toArray(new Class<?>[apis.size()]), new ClassLoaderAwareHandler(null, service, loader));
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java
index bd55d12..21bc831 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java
@@ -32,6 +32,7 @@ public class ServiceInfo extends InfoObject {
public String className;
public String codebase;
public URI[] classpath;
+ public String classpathAPI;
public Properties properties;
public final List<String> constructorArgs = new ArrayList<>();
public Properties unsetProperties; // keep it in the model to be able to investigate it dumping Infos
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
index e9fd1d1..873a092 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java
@@ -798,6 +798,8 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
service.setClasspath(cp);
}
+ service.setClasspathAPI(map.remove("classpath-api"));
+
if (object instanceof Resource) {
final Resource resource = Resource.class.cast(object);
final String aliases = map.remove("aliases");
@@ -1281,6 +1283,7 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory {
if (service.getClasspath() != null && service.getClasspath().length() > 0) {
info.classpath = resolveClasspath(service.getClasspath());
}
+ info.classpathAPI = service.getClasspathAPI();
specialProcessing(info);
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
index 58d9792..c0b4c16 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java
@@ -66,6 +66,8 @@ public interface Service {
String getClasspath();
+ String getClasspathAPI();
+
String getPropertiesProvider();
String getTemplate();
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
index 5771632..5e0690f 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java
@@ -51,17 +51,25 @@ public abstract class AbstractService implements Service {
@XmlValue
@XmlJavaTypeAdapter(PropertiesAdapter.class)
protected Properties properties;
+
@XmlAttribute(required = true)
protected String id;
+
@XmlAttribute
protected String jar;
+
@XmlAttribute
protected String provider;
+
@XmlAttribute
protected String type;
+
@XmlAttribute
protected String classpath;
+ @XmlAttribute(name = "classpath-api")
+ protected String classpathAPI;
+
/**
* Mutually exclusive with 'provider'
*/
@@ -205,6 +213,15 @@ public abstract class AbstractService implements Service {
this.className = className;
}
+ @Override
+ public String getClasspathAPI() {
+ return classpathAPI;
+ }
+
+ public void setClasspathAPI(final String classpathAPI) {
+ this.classpathAPI = classpathAPI;
+ }
+
public String getConstructor() {
return constructor;
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
index 9f14676..63da4dc 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java
@@ -183,6 +183,9 @@ public class StackHandler extends DefaultHandler {
if (attributes.getValue("classpath") != null) {
service.setClasspath(attributes.getValue("classpath"));
}
+ if (attributes.getValue("classpath-api") != null) {
+ service.setClasspathAPI(attributes.getValue("classpath-api"));
+ }
checkAttributes(attributes, getAttributes());
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java
new file mode 100644
index 0000000..068ee4b
--- /dev/null
+++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.Configuration;
+import org.apache.openejb.testng.PropertiesBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Resource;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+
+import static org.apache.openejb.loader.JarLocation.jarLocation;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@Classes
+@RunWith(ApplicationComposer.class)
+public class ClasspathAPITest {
+ @Configuration
+ public Properties config() {
+ return new PropertiesBuilder()
+ .p("r", "new://Resource?class-name=org.apache.openejb.resource.ClasspathAPITest$MyImpl&" +
+ "classpath-api=java.util.concurrent.Callable&" +
+ "classpath=" + jarLocation(ClasspathAPITest.class).toURI().toASCIIString())
+ .build();
+ }
+
+ @Resource(name = "r")
+ private Callable<String> impl;
+
+ @Test
+ public void check() throws Exception {
+ assertTrue(Callable.class.isInstance(impl));
+ assertFalse(Runnable.class.isInstance(impl));
+ assertEquals("ok", impl.call());
+ }
+
+ public static class MyImpl implements Runnable, Callable<String> {
+ @Override
+ public void run() {
+ fail();
+ }
+
+ @Override
+ public String call() throws Exception {
+ return "ok";
+ }
+ }
+}