Repository: tomee Updated Branches: refs/heads/master d60d52322 -> ce4c7ce45
TOMEE-1511 tolerating parallel deployments for jaxws Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/ce4c7ce4 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/ce4c7ce4 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/ce4c7ce4 Branch: refs/heads/master Commit: ce4c7ce454651660d58d88fe73f5f1cf5e81180a Parents: d60d523 Author: Romain Manni-Bucau <[email protected]> Authored: Tue Mar 24 08:53:55 2015 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Tue Mar 24 08:53:55 2015 +0100 ---------------------------------------------------------------------- .../openejb/monitoring/LocalMBeanServer.java | 4 +- .../webservices/OpenEJBHttpWsRegistry.java | 14 ++- .../openejb/server/webservices/WsRegistry.java | 10 +- .../openejb/server/webservices/WsService.java | 21 ++-- .../tomee/webservices/TomcatWsRegistry.java | 115 ++++++++++++++----- 5 files changed, 117 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/ce4c7ce4/container/openejb-core/src/main/java/org/apache/openejb/monitoring/LocalMBeanServer.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/LocalMBeanServer.java b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/LocalMBeanServer.java index 51d0d94..94b3b2f 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/LocalMBeanServer.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/LocalMBeanServer.java @@ -89,7 +89,7 @@ public final class LocalMBeanServer implements MBeanServer { return get().registerMBean(mbean, name); } catch (final Exception e) { - LOGGER.error("Cannot register MBean " + name, e); + LOGGER.error("Cannot register MBean " + name); // silently so no stack } return null; } @@ -103,7 +103,7 @@ public final class LocalMBeanServer implements MBeanServer { get().unregisterMBean(name); } catch (final Exception e) { - LOGGER.error("Cannot unregister MBean " + name, e); + LOGGER.error("Cannot unregister MBean " + name); // silently so no stack } } http://git-wip-us.apache.org/repos/asf/tomee/blob/ce4c7ce4/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/OpenEJBHttpWsRegistry.java ---------------------------------------------------------------------- diff --git a/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/OpenEJBHttpWsRegistry.java b/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/OpenEJBHttpWsRegistry.java index c9e2218..bfd0abd 100644 --- a/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/OpenEJBHttpWsRegistry.java +++ b/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/OpenEJBHttpWsRegistry.java @@ -29,16 +29,17 @@ public class OpenEJBHttpWsRegistry extends OpenEJBHttpRegistry implements WsRegi public List<String> setWsContainer(final HttpListener httpListener, final ClassLoader classLoader, final String context, final String virtualHost, final ServletInfo servletInfo, - final String realmName, final String transportGuarantee, final String authMethod) throws Exception { + final String realmName, final String transportGuarantee, final String authMethod, + final String moduleId) throws Exception { final String path = servletInfo.mappings.iterator().next(); - return addWsContainer(httpListener, classLoader, context, virtualHost, path, realmName, transportGuarantee, authMethod); + return addWsContainer(httpListener, classLoader, context, virtualHost, path, realmName, transportGuarantee, authMethod, moduleId); } @Override - public void clearWsContainer(final String context, final String virtualHost, final ServletInfo servletInfo) { + public void clearWsContainer(final String context, final String virtualHost, final ServletInfo servletInfo, final String moduleId) { final String path = servletInfo.mappings.iterator().next(); - removeWsContainer(path); + removeWsContainer(path, moduleId); } @Override @@ -49,7 +50,8 @@ public class OpenEJBHttpWsRegistry extends OpenEJBHttpRegistry implements WsRegi final String path, final String realmName, final String transportGuarantee, // ignored - final String authMethod) throws Exception { + final String authMethod, + final String moduleId) throws Exception { if (path == null) throw new NullPointerException("contextRoot is null"); @@ -84,7 +86,7 @@ public class OpenEJBHttpWsRegistry extends OpenEJBHttpRegistry implements WsRegi } @Override - public void removeWsContainer(final String path) { + public void removeWsContainer(final String path, final String moduleId) { registry.removeHttpListener(path); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/ce4c7ce4/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsRegistry.java ---------------------------------------------------------------------- diff --git a/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsRegistry.java b/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsRegistry.java index e9db64f..ed4a3df 100644 --- a/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsRegistry.java +++ b/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsRegistry.java @@ -25,9 +25,10 @@ public interface WsRegistry { List<String> setWsContainer(HttpListener httpListener, ClassLoader classLoader, String context, String virtualHost, ServletInfo servletInfo, - String realmName, String transportGuarantee, String authMethod) throws Exception; + String realmName, String transportGuarantee, String authMethod, + String moduleId) throws Exception; - void clearWsContainer(String context, String virtualHost, ServletInfo servletInfo); + void clearWsContainer(String context, String virtualHost, ServletInfo servletInfo, String moduleId); List<String> addWsContainer(HttpListener inputListener, ClassLoader classLoader, @@ -36,7 +37,8 @@ public interface WsRegistry { String path, String realmName, String transportGuarantee, // ignored - String authMethod) throws Exception; + String authMethod, + String moduleId) throws Exception; - void removeWsContainer(String path); + void removeWsContainer(String path, String moduleId); } http://git-wip-us.apache.org/repos/asf/tomee/blob/ce4c7ce4/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsService.java ---------------------------------------------------------------------- diff --git a/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsService.java b/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsService.java index 07e768b..3485f01 100644 --- a/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsService.java +++ b/server/openejb-webservices/src/main/java/org/apache/openejb/server/webservices/WsService.java @@ -238,17 +238,17 @@ public abstract class WsService implements ServerService, SelfManaging { private void deployApp(final AppInfo appInfo, final Collection<BeanContext> ejbs) { final Collection<BeanContext> alreadyDeployed = deployedApplications.get(appInfo); - final Map<String, String> webContextByEjb = new HashMap<String, String>(); + final Map<String, WebAppInfo> webContextByEjb = new HashMap<>(); for (final WebAppInfo webApp : appInfo.webApps) { for (final String ejb : webApp.ejbWebServices) { - webContextByEjb.put(ejb, webApp.contextRoot); + webContextByEjb.put(ejb, webApp); } } - final Map<String, String> contextData = new HashMap<String, String>(); + final Map<String, String> contextData = new HashMap<>(); contextData.put("appId", appInfo.path); for (final EjbJarInfo ejbJar : appInfo.ejbJars) { - final Map<String, PortInfo> ports = new TreeMap<String, PortInfo>(); + final Map<String, PortInfo> ports = new TreeMap<>(); for (final PortInfo port : ejbJar.portInfos) { ports.put(port.serviceLink, port); } @@ -312,12 +312,15 @@ public abstract class WsService implements ServerService, SelfManaging { transport = portInfo.transportGuarantee; } - String context = webContextByEjb.get(bean.ejbClass); + final WebAppInfo webAppInfo = webContextByEjb.get(bean.ejbClass); + String context = webAppInfo != null ? webAppInfo.contextRoot : null; + String moduleId = webAppInfo != null ? webAppInfo.moduleId : null; if (context == null && !OLD_WEBSERVICE_DEPLOYMENT) { context = ejbJar.moduleName; + context = null; } - final List<String> addresses = wsRegistry.addWsContainer(container, classLoader, context, host, location, realm, transport, auth); + final List<String> addresses = wsRegistry.addWsContainer(container, classLoader, context, host, location, realm, transport, auth, moduleId); alreadyDeployed.add(beanContext); // one of the registered addresses to be the canonical address @@ -431,7 +434,7 @@ public abstract class WsService implements ServerService, SelfManaging { } // give servlet a reference to the webservice container - final List<String> addresses = wsRegistry.setWsContainer(container, classLoader, webApp.contextRoot, host(webApp), servlet, realm, transport, auth); + final List<String> addresses = wsRegistry.setWsContainer(container, classLoader, webApp.contextRoot, host(webApp), servlet, realm, transport, auth, webApp.moduleId); // one of the registered addresses to be the connonical address final String address = HttpUtil.selectSingleAddress(addresses); @@ -488,7 +491,7 @@ public abstract class WsService implements ServerService, SelfManaging { // remove container from web server final String location = ejbLocations.get(enterpriseBean.ejbDeploymentId); if (this.wsRegistry != null && location != null) { - this.wsRegistry.removeWsContainer(location); + this.wsRegistry.removeWsContainer(location, ejbJar.moduleId); } // destroy webservice container @@ -528,7 +531,7 @@ public abstract class WsService implements ServerService, SelfManaging { // clear servlet's reference to the webservice container if (this.wsRegistry != null) { try { - this.wsRegistry.clearWsContainer(webApp.contextRoot, host(webApp), servlet); + this.wsRegistry.clearWsContainer(webApp.contextRoot, host(webApp), servlet, webApp.moduleId); } catch (final IllegalArgumentException ignored) { // no-op } http://git-wip-us.apache.org/repos/asf/tomee/blob/ce4c7ce4/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java b/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java index eedbaf4..b33976f 100644 --- a/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java +++ b/tomee/tomee-webservices/src/main/java/org/apache/tomee/webservices/TomcatWsRegistry.java @@ -52,7 +52,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +import static java.util.Arrays.asList; public class TomcatWsRegistry implements WsRegistry { private static final String WEBSERVICE_SUB_CONTEXT = forceSlash(SystemInstance.get().getOptions().get("tomee.jaxws.subcontext", "/webservices")); @@ -60,8 +62,8 @@ public class TomcatWsRegistry implements WsRegistry { private static final boolean WEBSERVICE_OLDCONTEXT_ACTIVE = SystemInstance.get().getOptions().get("tomee.jaxws.oldsubcontext", false); private static final String TOMEE_JAXWS_SECURITY_ROLE_PREFIX = "tomee.jaxws.security-role."; - private final Map<String, Context> webserviceContexts = new TreeMap<String, Context>(); - private final Map<String, Integer> fakeContextReferences = new TreeMap<String, Integer>(); + private final Map<Key, Context> webserviceContexts = new ConcurrentHashMap<>(); + private final Map<String, Integer> fakeContextReferences = new ConcurrentHashMap<>(); private Engine engine; private List<Connector> connectors; @@ -92,7 +94,8 @@ public class TomcatWsRegistry implements WsRegistry { public List<String> setWsContainer(final HttpListener httpListener, final ClassLoader classLoader, String contextRoot, String virtualHost, final ServletInfo servletInfo, - final String realmName, final String transportGuarantee, final String authMethod) throws Exception { + final String realmName, final String transportGuarantee, final String authMethod, + final String moduleId) throws Exception { if (virtualHost == null) { virtualHost = engine.getDefaultHost(); @@ -133,7 +136,7 @@ public class TomcatWsRegistry implements WsRegistry { setWsContainer(context, wrapper, httpListener); // add service locations - final List<String> addresses = new ArrayList<String>(); + final List<String> addresses = new ArrayList<>(); for (final Connector connector : connectors) { for (final String mapping : wrapper.findMappings()) { final URI address = new URI(connector.getScheme(), null, host.getName(), connector.getPort(), (contextRoot.startsWith("/") ? "" : "/") + contextRoot + mapping, null, null); @@ -145,7 +148,7 @@ public class TomcatWsRegistry implements WsRegistry { @Override - public void clearWsContainer(final String contextRoot, String virtualHost, final ServletInfo servletInfo) { + public void clearWsContainer(final String contextRoot, String virtualHost, final ServletInfo servletInfo, final String moduleId) { if (virtualHost == null) { virtualHost = engine.getDefaultHost(); } @@ -180,7 +183,8 @@ public class TomcatWsRegistry implements WsRegistry { public List<String> addWsContainer(final HttpListener httpListener, final ClassLoader classLoader, final String context, String virtualHost, String path, - final String realmName, final String transportGuarantee, final String authMethod) throws Exception { + final String realmName, final String transportGuarantee, final String authMethod, + final String moduleId) throws Exception { if (path == null) { throw new NullPointerException("contextRoot is null"); } @@ -202,7 +206,7 @@ public class TomcatWsRegistry implements WsRegistry { throw new IllegalArgumentException("Invalid virtual host '" + virtualHost + "'. Do you have a matchiing Host entry in the server.xml?"); } - final List<String> addresses = new ArrayList<String>(); + final List<String> addresses = new ArrayList<>(); // build contexts // - old way (/*) @@ -212,23 +216,16 @@ public class TomcatWsRegistry implements WsRegistry { // - new way (/<webappcontext>/webservices/<name>) if webcontext is specified if (context != null) { - String root = context; - if ("ROOT".equals(root)) { - root = ""; - } - if (!root.startsWith("/") && !root.isEmpty()) { - root = '/' + root; - } + final Context webAppContext = findContext(context, moduleId, host); - final Context webAppContext = Context.class.cast(host.findChild(root)); if (webAppContext != null) { // sub context = '/' means the service address is provided by webservices if (WEBSERVICE_SUB_CONTEXT.equals("/") && path.startsWith("/")) { - addServlet(host, webAppContext, path, httpListener, path, addresses, false); + addServlet(host, webAppContext, path, httpListener, path, addresses, false, moduleId); } else if (WEBSERVICE_SUB_CONTEXT.equals("/") && !path.startsWith("/")) { - addServlet(host, webAppContext, '/' + path, httpListener, path, addresses, false); + addServlet(host, webAppContext, '/' + path, httpListener, path, addresses, false, moduleId); } else { - addServlet(host, webAppContext, WEBSERVICE_SUB_CONTEXT + path, httpListener, path, addresses, false); + addServlet(host, webAppContext, WEBSERVICE_SUB_CONTEXT + path, httpListener, path, addresses, false, moduleId); } } else if (!WEBSERVICE_OLDCONTEXT_ACTIVE) { // deploying in a jar deployInFakeWebapp(path, classLoader, authMethod, transportGuarantee, realmName, host, httpListener, addresses, context); @@ -237,7 +234,30 @@ public class TomcatWsRegistry implements WsRegistry { return addresses; } - private void deployInFakeWebapp(final String path, final ClassLoader classLoader, final String authMethod, final String transportGuarantee, final String realmName, final Container host, final HttpListener httpListener, final List<String> addresses, final String name) { + private Context findContext(final String context, final String moduleId, final Container host) { + String root = context; + if ("ROOT".equals(root)) { + root = ""; + } + if (!root.startsWith("/") && !root.isEmpty()) { + root = '/' + root; + } + + Context webAppContext = null; + for (final String name : asList(moduleId == null ? null : "/" + moduleId, root)) { + if (name == null) { + continue; + } + webAppContext = Context.class.cast(host.findChild(name)); + if (webAppContext != null) { + break; + } + } + return webAppContext; + } + + private void deployInFakeWebapp(final String path, final ClassLoader classLoader, final String authMethod, final String transportGuarantee, + final String realmName, final Container host, final HttpListener httpListener, final List<String> addresses, final String name) { Container context = host.findChild(name); if (context == null) { context = createNewContext(classLoader, authMethod, transportGuarantee, realmName, name); @@ -255,7 +275,7 @@ public class TomcatWsRegistry implements WsRegistry { if (!mapping.startsWith("/")) { // TODO: check it can happen or move it away mapping = '/' + mapping; } - addServlet(host, (Context) context, mapping, httpListener, path, addresses, true); + addServlet(host, (Context) context, mapping, httpListener, path, addresses, true, null); } private static Context createNewContext(final ClassLoader classLoader, String authMethod, String transportGuarantee, final String realmName, final String name) { @@ -331,7 +351,8 @@ public class TomcatWsRegistry implements WsRegistry { return context; } - private void addServlet(final Container host, final Context context, final String mapping, final HttpListener httpListener, final String path, final List<String> addresses, final boolean fakeDeployment) { + private void addServlet(final Container host, final Context context, final String mapping, final HttpListener httpListener, final String path, + final List<String> addresses, final boolean fakeDeployment, final String moduleId) { // build the servlet final Wrapper wrapper = context.createWrapper(); wrapper.setName("webservice" + path.substring(1)); @@ -346,13 +367,13 @@ public class TomcatWsRegistry implements WsRegistry { setWsContainer(context, wrapper, httpListener); - webserviceContexts.put(path, context); + webserviceContexts.put(new Key(path, moduleId), context); // register wsdl locations for service-ref resolution for (final Connector connector : connectors) { final StringBuilder fullContextpath; if (!WEBSERVICE_OLDCONTEXT_ACTIVE && !fakeDeployment) { - String contextPath = context.getName(); + String contextPath = context.getPath(); if (contextPath == null || !contextPath.isEmpty()) { if (contextPath != null && !contextPath.startsWith("/")) { contextPath = "/" + contextPath; @@ -379,7 +400,7 @@ public class TomcatWsRegistry implements WsRegistry { } } - public void removeWsContainer(String path) { + public void removeWsContainer(String path, final String moduleId) { if (path == null) { return; } @@ -393,7 +414,11 @@ public class TomcatWsRegistry implements WsRegistry { return; } - final Context context = webserviceContexts.remove(path); + Context context = webserviceContexts.remove(new Key(path, moduleId)); + if (context == null) { // fake + context = webserviceContexts.remove(new Key(path, null)); + } + Integer refs = 1; // > 0 to avoid to destroy the context if not mandatory if (context != null) { final String name = context.getName(); @@ -423,4 +448,42 @@ public class TomcatWsRegistry implements WsRegistry { context.getServletContext().setAttribute(webServicecontainerID, wsContainer); wrapper.addInitParameter(WsServlet.WEBSERVICE_CONTAINER, webServicecontainerID); } + + private static class Key { + private final String moduleId; + private final String path; + private final int hash; + + public Key(final String moduleId, final String path) { + this.moduleId = moduleId; + this.path = path; + this.hash = 31 * (moduleId != null ? moduleId.hashCode() : 0) + path.hashCode(); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || Key.class != o.getClass()) { + return false; + } + + final Key key = Key.class.cast(o); + return !(moduleId != null ? !moduleId.equals(key.moduleId) : key.moduleId != null) && path.equals(key.path); + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public String toString() { + return "Key{" + + "moduleId='" + moduleId + '\'' + + ", path='" + path + '\'' + + '}'; + } + } }
