You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/29 21:31:58 UTC

[03/31] git commit: tidy initial pull request from @bmwshop, as per code review, plus some todo comments

tidy initial pull request from @bmwshop, as per code review, plus some todo comments


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/dbf26e3a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/dbf26e3a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/dbf26e3a

Branch: refs/heads/master
Commit: dbf26e3a46afa7a7b25374043a0e0969052d049f
Parents: 9c9f037
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jul 18 15:38:37 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Jul 29 10:41:10 2014 -0400

----------------------------------------------------------------------
 .../webapp/ControlledDynamicWebAppCluster.java  |  25 ++--
 .../ControlledDynamicWebAppClusterImpl.java     | 114 ++++++++++---------
 .../entity/webapp/DynamicWebAppClusterImpl.java |   2 +
 .../entity/webapp/JavaWebAppService.java        |  66 +++++++++++
 .../webapp/JavaWebAppSoftwareProcess.java       |  52 +--------
 5 files changed, 134 insertions(+), 125 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
index 17fc569..0c263d9 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
@@ -21,8 +21,6 @@ package brooklyn.entity.webapp;
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Group;
-import brooklyn.entity.annotation.Effector;
-import brooklyn.entity.annotation.EffectorParam;
 import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.ConfigurableEntityFactory;
@@ -59,8 +57,8 @@ import brooklyn.util.flags.SetFromFlag;
  * members has no effect on the members of the underlying DynamicCluster - treat this as a read-only view.
  */
 @ImplementedBy(ControlledDynamicWebAppClusterImpl.class)
-public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, Startable, Resizable, MemberReplaceable, Group, ElasticJavaWebAppService, JavaWebAppSoftwareProcess {
-
+public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, Startable, Resizable, MemberReplaceable, Group, ElasticJavaWebAppService, JavaWebAppService.CanDeployAndUndeploy, JavaWebAppService.CanRedeployAll {
+    
     @SetFromFlag("initialSize")
     public static ConfigKey<Integer> INITIAL_SIZE = ConfigKeys.newConfigKeyWithDefault(Cluster.INITIAL_SIZE, 1);
 
@@ -68,20 +66,24 @@ public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, St
     public static BasicAttributeSensorAndConfigKey<LoadBalancer> CONTROLLER = new BasicAttributeSensorAndConfigKey<LoadBalancer>(
         LoadBalancer.class, "controlleddynamicwebappcluster.controller", "Controller for the cluster; if null a default will created (using controllerSpec)");
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     @SetFromFlag("controllerSpec")
     public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends LoadBalancer>> CONTROLLER_SPEC = new BasicAttributeSensorAndConfigKey(
             EntitySpec.class, "controlleddynamicwebappcluster.controllerSpec", "Spec for creating the controller (if one not supplied explicitly); if null an NGINX instance will be created");
 
+    @SuppressWarnings({ "unchecked", "rawtypes", "deprecation" })
     /** factory (or closure) to create the web server, given flags */
     @SetFromFlag("factory")
     public static BasicAttributeSensorAndConfigKey<ConfigurableEntityFactory<? extends WebAppService>> FACTORY = new BasicAttributeSensorAndConfigKey(
             ConfigurableEntityFactory.class, DynamicCluster.FACTORY.getName(), "factory (or closure) to create the web server");
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     /** Spec for web server entiites to be created */
     @SetFromFlag("memberSpec")
     public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends WebAppService>> MEMBER_SPEC = new BasicAttributeSensorAndConfigKey(
             EntitySpec.class, DynamicCluster.MEMBER_SPEC.getName(), "Spec for web server entiites to be created");
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     @SetFromFlag("webClusterSpec")
     public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends DynamicWebAppCluster>> WEB_CLUSTER_SPEC = new BasicAttributeSensorAndConfigKey(
             EntitySpec.class, "controlleddynamicwebappcluster.webClusterSpec", "Spec for creating the cluster; if null a DynamicWebAppCluster will be created");
@@ -93,24 +95,11 @@ public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, St
 
     public static final AttributeSensor<Lifecycle> SERVICE_STATE = Attributes.SERVICE_STATE;
 
+    
     public LoadBalancer getController();
     
     public ConfigurableEntityFactory<WebAppService> getFactory();
     
     public DynamicWebAppCluster getCluster();
     
-    @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
-    public void deploy(
-            @EffectorParam(name="url", description="URL of WAR file") String url, 
-            @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName);
-
-    @Effector(description="Undeploys the given context/artifact")
-    public void undeploy(
-            @EffectorParam(name="targetName") String targetName); 
-    
-    @Effector(description="Updates the given context/artifact")
-    public void update(
-    		@EffectorParam(name="url", description="URL of NEW WAR file") String url,
-            @EffectorParam(name="targetName") String targetName);    
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
index 262f9f8..ac70f3a 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
@@ -18,6 +18,8 @@
  */
 package brooklyn.entity.webapp;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.List;
@@ -50,17 +52,14 @@ import brooklyn.event.feed.ConfigToAttributes;
 import brooklyn.location.Location;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
 import brooklyn.util.exceptions.Exceptions;
 
 import com.google.common.base.Predicate;
-import com.google.common.base.Throwables;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import brooklyn.entity.webapp.FilenameToWebContextMapper;
-import static com.google.common.base.Preconditions.checkNotNull;
 
 public class ControlledDynamicWebAppClusterImpl extends DynamicGroupImpl implements ControlledDynamicWebAppCluster {
 
@@ -337,76 +336,79 @@ public class ControlledDynamicWebAppClusterImpl extends DynamicGroupImpl impleme
         try {
             checkNotNull(url, "url");
             checkNotNull(targetName, "targetName");
-            // actually deploy
-            List <Entity> cluster_members = Lists.newArrayList();
-//            cluster_members.addAll((Collection<? extends Entity>) Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class)); 
-            for (JavaWebAppSoftwareProcess member : Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class)) {
-            	Lifecycle serviceState = member.getAttribute(SERVICE_STATE);
-            	if (serviceState == Lifecycle.RUNNING) {
-            	  cluster_members.add(member);
-            	}
-            }            
-            Entities.invokeEffectorListWithArgs(this, cluster_members, DEPLOY, url, targetName).get();            
             
-            // Update attribute
-            Set<String> deployedWars = getAttribute(DEPLOYED_WARS);
-            if (deployedWars == null) {
-                deployedWars = Sets.newLinkedHashSet();
+            // set it up so future nodes get the right wars
+            synchronized (this) {
+                Map<String,String> newWarsMap = MutableMap.copyOf(getConfig(WARS_BY_CONTEXT));
+                newWarsMap.put(targetName, url);
+                setConfig(WARS_BY_CONTEXT, newWarsMap);
             }
+            
+            // now actually deploy
+            List <Entity> clusterMembers = MutableList.copyOf(
+                Iterables.filter(getCluster().getChildren(), Predicates.and(
+                     Predicates.instanceOf(JavaWebAppSoftwareProcess.class),
+                     EntityPredicates.attributeEqualTo(SERVICE_STATE, Lifecycle.RUNNING)
+            )));
+            Entities.invokeEffectorListWithArgs(this, clusterMembers, DEPLOY, url, targetName).get();            
+            
+            // Update attribute
+            Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS));
             deployedWars.add(targetName);
             setAttribute(DEPLOYED_WARS, deployedWars);
-        } catch (RuntimeException e) {
+            
+        } catch (Exception e) {
             // Log and propagate, so that log says which entity had problems...
             log.warn("Error deploying '"+url+"' to "+targetName+" on "+toString()+"; rethrowing...", e);
-            throw Throwables.propagate(e);
-        } catch (Throwable th) {
-            // Log and propagate, so that log says which entity had problems...
-            log.warn("Error undeploying '"+targetName+"' on "+toString()+"; rethrowing...", th);
-            throw Throwables.propagate(th);
+            throw Exceptions.propagate(e);
         }
     }
+    
+    /*
+     * TODO
+     * 
+     * - deploy to all, not just running, with a wait-for-running-or-bail-out logic
+     * - thread pool
+     * - redeploy to all (simple way, with notes)
+     * - check-in, then move down with echo here
+     */
+    
     /** For the DEPLOYED_WARS to be updated, the input must match the result of the call to deploy */
     @Effector(description="Undeploys the given context/artifact")
-    public void undeploy(
-            @EffectorParam(name="targetName") String targetName) {
+    public void undeploy(@EffectorParam(name="targetName") String targetName) {
     	
         try {
+            checkNotNull(targetName, "targetName");
+            
+            // set it up so future nodes get the right wars
+            synchronized (this) {
+                Map<String,String> newWarsMap = MutableMap.copyOf(getConfig(WARS_BY_CONTEXT));
+                newWarsMap.remove(targetName);
+                setConfig(WARS_BY_CONTEXT, newWarsMap);
+            }
 
-            List <Entity> cluster_members = Lists.newArrayList();
-//            cluster_members.addAll((Collection<? extends Entity>) Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class));
-            for (JavaWebAppSoftwareProcess member : Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class)) {
-            	Lifecycle serviceState = member.getAttribute(SERVICE_STATE);
-            	if (serviceState == Lifecycle.RUNNING) {
-            	  cluster_members.add(member);
-            	}
-            }             
-            Entities.invokeEffectorListWithArgs(this, cluster_members, UNDEPLOY, targetName).get(); 
+            List <Entity> clusterMembers = MutableList.copyOf(
+                Iterables.filter(getCluster().getChildren(), Predicates.and(
+                     Predicates.instanceOf(JavaWebAppSoftwareProcess.class),
+                     EntityPredicates.attributeEqualTo(SERVICE_STATE, Lifecycle.RUNNING)
+            )));
+            Entities.invokeEffectorListWithArgs(this, clusterMembers, UNDEPLOY, targetName).get(); 
             
-       	
             // Update attribute
-            Set<String> deployedWars = getAttribute(DEPLOYED_WARS);
-            if (deployedWars == null) {
-                deployedWars = Sets.newLinkedHashSet();
-            }
+            Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS));
             deployedWars.remove( filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName) );
             setAttribute(DEPLOYED_WARS, deployedWars);
-        } catch (RuntimeException e) {
+            
+        } catch (Exception e) {
             // Log and propagate, so that log says which entity had problems...
             log.warn("Error undeploying '"+targetName+"' on "+toString()+"; rethrowing...", e);
-            throw Throwables.propagate(e);
-        } catch (Throwable th) {
-            // Log and propagate, so that log says which entity had problems...
-            log.warn("Error undeploying '"+targetName+"' on "+toString()+"; rethrowing...", th);
-            throw Throwables.propagate(th);
+            throw Exceptions.propagate(e);
         }
+    }
+
+    @Override
+    public void redeployAll() {
+        throw new UnsupportedOperationException("TODO - support redeploying all WARs (if any of the deploy/undeploys fail)");
     }  
-    @Effector(description="Updates the given context/artifact")
-    public void update(
-    		@EffectorParam(name="url", description="URL of NEW WAR file") String url,
-            @EffectorParam(name="targetName") String targetName) {
-    	// simple for now
-    	undeploy(targetName);
-    	deploy(url, targetName);
-    
-    }    
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
index 360870f..ec942ee 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
@@ -82,7 +82,9 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
         }
         
         for (List<? extends AttributeSensor<? extends Number>> es : averagingEnricherSetup) {
+            @SuppressWarnings("unchecked")
             AttributeSensor<Number> t = (AttributeSensor<Number>) es.get(0);
+            @SuppressWarnings("unchecked")
             AttributeSensor<Double> average = (AttributeSensor<Double>) es.get(1);
             addEnricher(Enrichers.builder()
                     .aggregating(t)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
index 044f49c..8561c12 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
@@ -20,9 +20,15 @@ package brooklyn.entity.webapp;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import brooklyn.config.ConfigKey;
+import brooklyn.entity.annotation.Effector;
+import brooklyn.entity.annotation.EffectorParam;
+import brooklyn.entity.basic.MethodEffector;
 import brooklyn.entity.java.UsesJava;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
 import brooklyn.event.basic.BasicConfigKey;
 import brooklyn.util.flags.SetFromFlag;
 
@@ -32,11 +38,71 @@ public interface JavaWebAppService extends WebAppService, UsesJava {
 	public static final ConfigKey<String> ROOT_WAR = new BasicConfigKey<String>(
 	        String.class, "wars.root", "WAR file to deploy as the ROOT, as URL (supporting file: and classpath: prefixes)");
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     @SetFromFlag("wars")
 	public static final ConfigKey<List<String>> NAMED_WARS = new BasicConfigKey(
 	        List.class, "wars.named", "Archive files to deploy, as URL strings (supporting file: and classpath: prefixes); context (path in user-facing URL) will be inferred by name");
     
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     @SetFromFlag("warsByContext")
     public static final ConfigKey<Map<String,String>> WARS_BY_CONTEXT = new BasicConfigKey(
             Map.class, "wars.by.context", "Map of context keys (path in user-facing URL, typically without slashes) to archives (e.g. WARs by URL) to deploy, supporting file: and classpath: prefixes)");
+    
+    /** Optional marker interface for entities which support 'deploy' and 'undeploy' */
+    public interface CanDeployAndUndeploy {
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        public static final AttributeSensor<Set<String>> DEPLOYED_WARS = new BasicAttributeSensor(
+                Set.class, "webapp.deployedWars", "Names of archives/contexts that are currently deployed");
+
+        public static final MethodEffector<Void> DEPLOY = new MethodEffector<Void>(CanDeployAndUndeploy.class, "deploy");
+        public static final MethodEffector<Void> UNDEPLOY = new MethodEffector<Void>(CanDeployAndUndeploy.class, "undeploy");
+
+        /**
+         * Deploys the given artifact, from a source URL, to a given deployment filename/context.
+         * There is some variance in expected filename/context at various servers,
+         * so the following conventions are followed:
+         * <p>
+         *   either ROOT.WAR or /       denotes root context
+         * <p>
+         *   anything of form  FOO.?AR  (ending .?AR) is copied with that name (unless copying not necessary)
+         *                              and is expected to be served from /FOO
+         * <p>
+         *   anything of form  /FOO     (with leading slash) is expected to be served from /FOO
+         *                              (and is copied as FOO.WAR)
+         * <p>
+         *   anything of form  FOO      (without a dot) is expected to be served from /FOO
+         *                              (and is copied as FOO.WAR)
+         * <p>
+         *   otherwise <i>please note</i> behaviour may vary on different appservers;
+         *   e.g. FOO.FOO would probably be ignored on appservers which expect a file copied across (usually),
+         *   but served as /FOO.FOO on systems that take a deployment context.
+         * <p>
+         * See {@link FileNameToContextMappingTest} for definitive examples!
+         *
+         * @param url  where to get the war, as a URL, either classpath://xxx or file:///home/xxx or http(s)...
+         * @param targetName  where to tell the server to serve the WAR, see above
+         */
+        @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
+        public void deploy(
+                @EffectorParam(name="url", description="URL of WAR file") String url, 
+                @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName);
+
+        /** 
+         * For the DEPLOYED_WARS to be updated, the input must match the result of the call to deploy,
+         * e.g. the transformed name using 
+         */
+        @Effector(description="Undeploys the given context/artifact")
+        public void undeploy(
+                @EffectorParam(name="targetName") String targetName);
+    }
+
+    /** Optional marker interface for entities which support 'redeployAll' */
+    public interface CanRedeployAll {
+        public static final MethodEffector<Void> REDEPLOY_ALL = new MethodEffector<Void>(CanRedeployAll.class, "redeployAll");
+        
+        @Effector(description="Redeploys all web apps known here across the cluster (e.g. if it gets into an inconsistent state)")
+        public void redeployAll();
+    }
+        
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
index a6b43e2..5460f79 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
@@ -18,57 +18,7 @@
  */
 package brooklyn.entity.webapp;
 
-import java.util.Set;
-
-import brooklyn.entity.annotation.Effector;
-import brooklyn.entity.annotation.EffectorParam;
-import brooklyn.entity.basic.MethodEffector;
 import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-
-public interface JavaWebAppSoftwareProcess extends SoftwareProcess, JavaWebAppService {
-
-    public static final AttributeSensor<Set<String>> DEPLOYED_WARS = new BasicAttributeSensor(
-            Set.class, "webapp.deployedWars", "Names of archives/contexts that are currently deployed");
-
-    public static final MethodEffector<Void> DEPLOY = new MethodEffector<Void>(JavaWebAppSoftwareProcess.class, "deploy");
-    public static final MethodEffector<Void> UNDEPLOY = new MethodEffector<Void>(JavaWebAppSoftwareProcess.class, "undeploy");
-
-    /**
-     * Deploys the given artifact, from a source URL, to a given deployment filename/context.
-     * There is some variance in expected filename/context at various servers,
-     * so the following conventions are followed:
-     * <p>
-     *   either ROOT.WAR or /       denotes root context
-     * <p>
-     *   anything of form  FOO.?AR  (ending .?AR) is copied with that name (unless copying not necessary)
-     *                              and is expected to be served from /FOO
-     * <p>
-     *   anything of form  /FOO     (with leading slash) is expected to be served from /FOO
-     *                              (and is copied as FOO.WAR)
-     * <p>
-     *   anything of form  FOO      (without a dot) is expected to be served from /FOO
-     *                              (and is copied as FOO.WAR)
-     * <p>
-     *   otherwise <i>please note</i> behaviour may vary on different appservers;
-     *   e.g. FOO.FOO would probably be ignored on appservers which expect a file copied across (usually),
-     *   but served as /FOO.FOO on systems that take a deployment context.
-     * <p>
-     * See {@link FileNameToContextMappingTest} for definitive examples!
-     *
-     * @param url  where to get the war, as a URL, either classpath://xxx or file:///home/xxx or http(s)...
-     * @param targetName  where to tell the server to serve the WAR, see above
-     */
-    @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
-    public void deploy(
-            @EffectorParam(name="url", description="URL of WAR file") String url, 
-            @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName);
 
-    /** 
-     * For the DEPLOYED_WARS to be updated, the input must match the result of the call to deploy
-     */
-    @Effector(description="Undeploys the given context/artifact")
-    public void undeploy(
-            @EffectorParam(name="targetName") String targetName);
+public interface JavaWebAppSoftwareProcess extends SoftwareProcess, JavaWebAppService, JavaWebAppService.CanDeployAndUndeploy {
 }