You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2008/08/14 23:33:47 UTC

svn commit: r686050 - in /openejb/trunk/openejb3/container/openejb-spring/src: main/java/org/apache/openejb/spring/ test/java/org/apache/openejb/spring/ test/resources/org/apache/openejb/spring/

Author: dain
Date: Thu Aug 14 14:33:46 2008
New Revision: 686050

URL: http://svn.apache.org/viewvc?rev=686050&view=rev
Log:
Added Spring application and ejb deployment

Added:
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractContainerProvider.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractResourceProvider.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBResource.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ResourceProvider.java
Modified:
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Application.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/BmpContainer.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/CmpContainer.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ContainerProvider.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/EJB.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/MdbContainer.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJB.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBDataSource.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Resource.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SingletonContainer.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringAssembler.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatefulContainer.java
    openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatelessContainer.java
    openejb/trunk/openejb3/container/openejb-spring/src/test/java/org/apache/openejb/spring/SpringTest.java
    openejb/trunk/openejb3/container/openejb-spring/src/test/resources/org/apache/openejb/spring/spring.xml

Added: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractContainerProvider.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractContainerProvider.java?rev=686050&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractContainerProvider.java (added)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractContainerProvider.java Thu Aug 14 14:33:46 2008
@@ -0,0 +1,76 @@
+/**
+ *
+ * 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.spring;
+
+import java.util.Properties;
+
+import org.springframework.beans.factory.BeanNameAware;
+import org.apache.openejb.config.sys.Container;
+import org.apache.openejb.OpenEJBException;
+
+public abstract class AbstractContainerProvider implements ContainerProvider, BeanNameAware {
+    private String id;
+    private String beanName;
+    private String provider;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setBeanName(String beanName) {
+        this.beanName = beanName;
+    }
+
+    public String getProvider() {
+        return provider;
+    }
+
+    public void setProvider(String provider) {
+        this.provider = provider;
+    }
+
+    public Container getContainerDefinition() throws OpenEJBException {
+        Container container = new Container();
+        container.setCtype(getContainerType());
+
+        if (id != null) {
+            container.setId(id);
+        } else if (beanName != null) {
+            container.setId(beanName);
+        } else {
+            throw new OpenEJBException("No id defined for SingletonContainer");
+        }
+
+        if (provider != null) {
+            container.setProvider(provider);
+        }
+
+        Properties properties = getProperties();
+        container.getProperties().putAll(properties);
+
+        return container;
+    }
+
+    protected abstract String getContainerType();
+
+    protected abstract Properties getProperties();
+}

Added: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractResourceProvider.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractResourceProvider.java?rev=686050&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractResourceProvider.java (added)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/AbstractResourceProvider.java Thu Aug 14 14:33:46 2008
@@ -0,0 +1,78 @@
+/**
+ *
+ * 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.spring;
+
+import java.util.Properties;
+
+import org.springframework.beans.factory.BeanNameAware;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.config.sys.Resource;
+
+public abstract class AbstractResourceProvider implements ResourceProvider, BeanNameAware {
+    private String id;
+    private String beanName;
+    private String provider;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setBeanName(String beanName) {
+        this.beanName = beanName;
+    }
+
+    public String getProvider() {
+        return provider;
+    }
+
+    public void setProvider(String provider) {
+        this.provider = provider;
+    }
+
+    public abstract String getType();
+
+    public abstract Properties getProperties();
+
+    public Resource getResourceDefinition() throws OpenEJBException {
+        Resource resource = new Resource();
+
+        if (id != null) {
+            resource.setId(id);
+        } else if (beanName != null) {
+            resource.setId(beanName);
+        } else {
+            throw new OpenEJBException("No id defined for Resource");
+        }
+
+        if (provider != null) {
+            resource.setProvider(provider);
+        }
+
+        if (getType() != null) {
+            resource.setType(getType());
+        }
+
+        resource.getProperties().putAll(getProperties());
+
+        return resource;
+    }
+}

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Application.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Application.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Application.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Application.java Thu Aug 14 14:33:46 2008
@@ -25,8 +25,8 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
-import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
+import javax.annotation.PostConstruct;
 
 import org.apache.openejb.Container;
 import org.apache.openejb.DeploymentInfo;
@@ -40,17 +40,21 @@
 import org.apache.openejb.config.ConfigurationFactory;
 import org.apache.openejb.config.DeploymentsResolver;
 import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
+import org.springframework.beans.factory.annotation.Required;
 
+@Exported
 public class Application {
     private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, Application.class);
     private final ConfigurationFactory configurationFactory = new ConfigurationFactory();
     private final List<AppInfo> applications = new ArrayList<AppInfo>();
-    private final Map<Object, DeploymentInfo> deployments = new LinkedHashMap<Object, DeploymentInfo>();
+    private final Map<Object, DeploymentInfo> notDeployed = new LinkedHashMap<Object, DeploymentInfo>();
 
     private OpenEJB openEJB;
     private boolean classpathAsEar = true;
+    private boolean started = false;
 
     public OpenEJB getOpenEJB() {
         return openEJB;
@@ -68,11 +72,13 @@
         this.classpathAsEar = classpathAsEar;
     }
 
-    @PostConstruct
-    public void start() throws Exception {
-        System.out.println();
-        System.out.println();
-        System.out.println();
+    // Do not make this the Spring start method
+    public void deployApplication() throws OpenEJBException {
+        // Ok someone made this the OpenEJB start method... ignore this deploy call
+        if (openEJB != null && openEJB.isStarting()) return;
+
+        if (started) return;
+        started = true;
 
         Set<String> declaredApplications = getDeployedApplications();
 
@@ -93,25 +99,35 @@
         Assembler assembler = getAssembler();
         if (classpathAsEar) {
             AppInfo appInfo = configurationFactory.configureApplication(classLoader, "classpath.ear", jarFiles);
+            deployApplication(assembler, appInfo);
+        } else {
+            for (File jarFile : jarFiles) {
+                AppInfo appInfo = configurationFactory.configureApplication(jarFile);
+                deployApplication(assembler, appInfo);
+            }
+        }
+    }
+
+    private void deployApplication(Assembler assembler, AppInfo appInfo) throws OpenEJBException {
+        try {
             List<DeploymentInfo> deployments = assembler.createApplication(appInfo, assembler.createAppClassLoader(appInfo), false);
             for (DeploymentInfo deployment : deployments) {
-                this.deployments.put(deployment.getDeploymentID(), deployment);
+                this.notDeployed.put(deployment.getDeploymentID(), deployment);
             }
             applications.add(appInfo);
-        } else {
-            for (File jarFile : jarFiles) {
-                AppInfo appInfo = configurationFactory.configureApplication(jarFile);
-                List<DeploymentInfo> deployments = assembler.createApplication(appInfo, assembler.createAppClassLoader(appInfo), false);
-                for (DeploymentInfo deployment : deployments) {
-                    this.deployments.put(deployment.getDeploymentID(), deployment);
-                }
-                applications.add(appInfo);
+        } catch (Exception e) {
+            if (e instanceof OpenEJBException) {
+                throw (OpenEJBException) e;
             }
+            throw new OpenEJBException("Error starting application " + appInfo.jarPath, e);
         }
     }
 
     @PreDestroy
     public void stop() {
+        if (!started) return;
+        started = false;
+
         for (AppInfo application : applications) {
             try {
                 getAssembler().destroyApplication(application.jarPath);
@@ -123,8 +139,20 @@
 
     public void startEjb(Object deploymentId) throws OpenEJBException {
         if (deploymentId == null) throw new NullPointerException("deploymentId is null");
-        DeploymentInfo deployment = deployments.get(deploymentId);
-        if (deployment == null) throw new IllegalArgumentException("Unknown deployment " + deploymentId);
+
+        deployApplication();
+
+        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+        DeploymentInfo deployment = containerSystem.getDeploymentInfo(deploymentId);
+        if (deployment == null) {
+            throw new IllegalArgumentException("Unknwon EJB " + deployment);
+        }
+
+        deployment = notDeployed.remove(deploymentId);
+        if (deployment == null) {
+            // already deployed
+            return;
+        }
 
         Container container = deployment.getContainer();
         container.deploy(deployment);
@@ -159,24 +187,4 @@
         }
         return declaredApps;
     }
-
-    private static class ApplicationData {
-        private final AppInfo appInfo;
-        private final Map<Object, DeploymentInfo> deployments = new LinkedHashMap<Object, DeploymentInfo>();
-
-        private ApplicationData(AppInfo appInfo, List<DeploymentInfo> deployments) {
-            this.appInfo = appInfo;
-            for (DeploymentInfo deployment : deployments) {
-                this.deployments.put(deployment.getDeploymentID(), deployment);
-            }
-        }
-
-        public DeploymentInfo getDeploymentInfo(Object deploymentId) {
-            return deployments.get(deploymentId);
-        }
-
-        public DeploymentInfo removeDeploymentInfo(Object deploymentId) {
-            return deployments.remove(deploymentId);
-        }
-    }
 }

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/BmpContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/BmpContainer.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/BmpContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/BmpContainer.java Thu Aug 14 14:33:46 2008
@@ -19,37 +19,11 @@
 
 import java.util.Properties;
 
-import org.springframework.beans.factory.BeanNameAware;
-import org.apache.openejb.config.sys.Container;
 import org.apache.openejb.config.BeanTypes;
-import org.apache.openejb.OpenEJBException;
 
-public class BmpContainer implements ContainerProvider, BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
+public class BmpContainer extends AbstractContainerProvider {
     private Integer poolSize;
 
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
-    }
-
-    public String getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String provider) {
-        this.provider = provider;
-    }
-
     public Integer getPoolSize() {
         return poolSize;
     }
@@ -58,26 +32,15 @@
         this.poolSize = poolSize;
     }
 
-    public Container getContainerDefinition() throws OpenEJBException {
-        Container container = new Container();
-        container.setCtype(BeanTypes.BMP_ENTITY);
-
-        if (id != null) {
-            container.setId(id);
-        } else if (beanName != null) {
-            container.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for BmpContainer");
-        }
-
-        if (provider != null) {
-            container.setProvider(provider);
-        }
+    protected String getContainerType() {
+        return BeanTypes.BMP_ENTITY;
+    }
 
-        Properties properties = container.getProperties();
+    protected Properties getProperties() {
+        Properties properties = new Properties();
         if (poolSize != null) {
             properties.put("PoolSize", poolSize);
         }
-        return container;
+        return properties;
     }
 }

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/CmpContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/CmpContainer.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/CmpContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/CmpContainer.java Thu Aug 14 14:33:46 2008
@@ -19,37 +19,11 @@
 
 import java.util.Properties;
 
-import org.springframework.beans.factory.BeanNameAware;
-import org.apache.openejb.config.sys.Container;
 import org.apache.openejb.config.BeanTypes;
-import org.apache.openejb.OpenEJBException;
 
-public class CmpContainer implements ContainerProvider, BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
+public class CmpContainer extends AbstractContainerProvider {
     private String cmpEngineFactory;
 
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
-    }
-
-    public String getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String provider) {
-        this.provider = provider;
-    }
-
     public String getCmpEngineFactory() {
         return cmpEngineFactory;
     }
@@ -58,26 +32,15 @@
         this.cmpEngineFactory = cmpEngineFactory;
     }
 
-    public Container getContainerDefinition() throws OpenEJBException {
-        Container container = new Container();
-        container.setCtype(BeanTypes.CMP_ENTITY);
-
-        if (id != null) {
-            container.setId(id);
-        } else if (beanName != null) {
-            container.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for CmpContainer");
-        }
-
-        if (provider != null) {
-            container.setProvider(provider);
-        }
+    protected String getContainerType() {
+        return BeanTypes.CMP_ENTITY;
+    }
 
-        Properties properties = container.getProperties();
+    protected Properties getProperties() {
+        Properties properties = new Properties();
         if (cmpEngineFactory != null) {
             properties.put("CmpEngineFactory", cmpEngineFactory);
         }
-        return container;
+        return properties;
     }
 }
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ContainerProvider.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ContainerProvider.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ContainerProvider.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ContainerProvider.java Thu Aug 14 14:33:46 2008
@@ -21,7 +21,5 @@
 import org.apache.openejb.config.sys.Container;
 
 public interface ContainerProvider {
-    String getId();
-
     Container getContainerDefinition() throws OpenEJBException;
 }

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/EJB.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/EJB.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/EJB.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/EJB.java Thu Aug 14 14:33:46 2008
@@ -19,15 +19,18 @@
 
 import javax.annotation.PostConstruct;
 
-import org.springframework.beans.factory.annotation.Required;
-import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.DeploymentInfo;
+import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.spi.ContainerSystem;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.annotation.Required;
 
-public class EJB {
+@Exported
+public class EJB<T> implements FactoryBean {
     private Application application;
     private Object deploymentId;
+    private Class<T> intf;
 
     public Application getApplication() {
         return application;
@@ -47,14 +50,47 @@
         this.deploymentId = deploymentId;
     }
 
+    public Class<T> getInterface() {
+        return intf;
+    }
+
+    @Required
+    public void setInterface(Class<T> intf) {
+        this.intf = intf;
+    }
+
     @PostConstruct
     public void start() throws OpenEJBException {
+    }
+
+    public T getObject() throws Exception {
         if (application == null) throw new NullPointerException("application is null");
         if (deploymentId == null) throw new NullPointerException("deploymentId is null");
+        if (intf == null) throw new NullPointerException("intf is null");
 
         application.startEjb(deploymentId);
 
         ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
         DeploymentInfo deploymentInfo = containerSystem.getDeploymentInfo(deploymentId);
+        if (deploymentInfo == null) {
+            throw new IllegalArgumentException("Unknwon EJB " + deploymentInfo);
+        }
+        
+        String jndiName = "java:openejb/Deployment/" + deploymentId + "/" + getInterface().getName();
+
+        Object proxy = containerSystem.getJNDIContext().lookup(jndiName);
+        if (!intf.isInstance(proxy)) {
+            throw new IllegalArgumentException(
+                    "EJB at " + jndiName + " is not an instance of " + intf.getName() + ", but is " + proxy.getClass().getName());
+        }
+        return intf.cast(proxy);
+    }
+
+    public Class<T> getObjectType() {
+        return getInterface();
+    }
+
+    public boolean isSingleton() {
+        return false;
     }
 }

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/MdbContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/MdbContainer.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/MdbContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/MdbContainer.java Thu Aug 14 14:33:46 2008
@@ -19,40 +19,14 @@
 
 import java.util.Properties;
 
-import org.springframework.beans.factory.BeanNameAware;
-import org.apache.openejb.config.sys.Container;
 import org.apache.openejb.config.BeanTypes;
-import org.apache.openejb.OpenEJBException;
 
-public class MdbContainer implements ContainerProvider, BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
+public class MdbContainer extends AbstractContainerProvider {
     private String resourceAdapter;
     private String messageListenerInterface;
     private String activationSpecClass;
     private Integer instanceLimit;
 
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
-    }
-
-    public String getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String provider) {
-        this.provider = provider;
-    }
-
     public String getResourceAdapter() {
         return resourceAdapter;
     }
@@ -85,23 +59,12 @@
         this.instanceLimit = instanceLimit;
     }
 
-    public Container getContainerDefinition() throws OpenEJBException {
-        Container container = new Container();
-        container.setCtype(BeanTypes.MESSAGE);
-
-        if (id != null) {
-            container.setId(id);
-        } else if (beanName != null) {
-            container.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for MdbContainer");
-        }
-
-        if (provider != null) {
-            container.setProvider(provider);
-        }
+    protected String getContainerType() {
+        return BeanTypes.MESSAGE;
+    }
 
-        Properties properties = container.getProperties();
+    protected Properties getProperties() {
+        Properties properties = new Properties();
         if (resourceAdapter != null) {
             properties.put("ResourceAdapter", resourceAdapter);
         }
@@ -114,6 +77,6 @@
         if (instanceLimit != null) {
             properties.put("InstanceLimit", instanceLimit);
         }
-        return container;
+        return properties;
     }
 }
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJB.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJB.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJB.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJB.java Thu Aug 14 14:33:46 2008
@@ -75,10 +75,11 @@
 
     private final Collection<ContainerProvider> containers = new ArrayList<ContainerProvider>();
 
-    private final Collection<Resource> resources = new ArrayList<Resource>();
+    private final Collection<ResourceProvider> resources = new ArrayList<ResourceProvider>();
 
     private boolean importContext = true;
 
+    private boolean starting;
     private Throwable initialized;
     private ApplicationContext applicationContext;
 
@@ -131,16 +132,16 @@
         return containers;
     }
 
-    public void setContainers(Collection<ContainerProvider> containers) {
+    public void setContainers(Collection<? extends ContainerProvider> containers) {
         this.containers.clear();
         this.containers.addAll(containers);
     }
 
-    public Collection<Resource> getResources() {
+    public Collection<ResourceProvider> getResources() {
         return resources;
     }
 
-    public void setResources(Collection<Resource> resources) {
+    public void setResources(Collection<? extends ResourceProvider> resources) {
         this.resources.clear();
         this.resources.addAll(resources);
     }
@@ -162,6 +163,10 @@
         return context;
     }
 
+    public boolean isStarting() {
+        return starting;
+    }
+
     public boolean isStarted() {
         return initialized != null || SystemInstance.get().getComponent(ContainerSystem.class) != null;
     }
@@ -182,7 +187,14 @@
                 throw new OpenEJBException(msg);
             }
         }
-        initialized = new Exception("Initialized at " + new Date()).fillInStackTrace();
+
+        //
+        // Is this bean already starting?  This helps avoid anoying spring loop backs.
+        //
+        if (starting) {
+            throw new OpenEJBException("OpenEJB already starting");
+        }
+        starting = true;
 
         //
         // System Instance
@@ -278,6 +290,8 @@
         //
         // Done
         //
+        initialized = new Exception("Initialized at " + new Date()).fillInStackTrace();
+        starting = false;
         logger.debug("startup.ready");
     }
 

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBDataSource.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBDataSource.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBDataSource.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBDataSource.java Thu Aug 14 14:33:46 2008
@@ -17,40 +17,11 @@
  */
 package org.apache.openejb.spring;
 
-import javax.naming.Context;
 import javax.sql.DataSource;
 
-import org.apache.openejb.loader.SystemInstance;
-import org.apache.openejb.spi.ContainerSystem;
-import org.springframework.beans.factory.FactoryBean;
-
 @Exported
-public class OpenEJBDataSource implements FactoryBean {
-    private String resourceId;
-
-    public String getResourceId() {
-        return resourceId;
-    }
-
-    public void setResourceId(String resourceId) {
-        this.resourceId = resourceId;
-    }
-
-    public Object getObject() throws Exception {
-        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
-        if (containerSystem == null) return null;
-        Context initialContext = containerSystem.getJNDIContext();
-        if (initialContext == null) return null;
-
-        DataSource dataSource = (DataSource) initialContext.lookup("openejb/Resource/" + resourceId);
-        return dataSource;
-    }
-
-    public Class getObjectType() {
-        return DataSource.class;
-    }
-
-    public boolean isSingleton() {
-        return false;
+public class OpenEJBDataSource extends OpenEJBResource<DataSource> {
+    public OpenEJBDataSource() {
+        super(DataSource.class);
     }
 }

Added: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBResource.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBResource.java?rev=686050&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBResource.java (added)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/OpenEJBResource.java Thu Aug 14 14:33:46 2008
@@ -0,0 +1,66 @@
+/**
+ *
+ * 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.spring;
+
+import javax.naming.Context;
+
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import org.springframework.beans.factory.FactoryBean;
+
+public class OpenEJBResource<T> implements FactoryBean {
+    private final Class<T> type;
+    private String resourceId;
+
+    public OpenEJBResource(Class<T> type) {
+        if (type == null) throw new NullPointerException("type is null");
+        this.type = type;
+    }
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public T getObject() throws Exception {
+        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+        if (containerSystem == null) return null;
+        Context initialContext = containerSystem.getJNDIContext();
+        if (initialContext == null) return null;
+
+        Object resource = initialContext.lookup("openejb/Resource/" + resourceId);
+
+        if (!type.isInstance(resource)) {
+            throw new IllegalArgumentException(
+                    "Resouce " + getResourceId() + " is not an instance of " + type.getSimpleName() + ", but is " + resource.getClass().getName());
+        }
+
+        return type.cast(resource);
+    }
+
+    public Class<T> getObjectType() {
+        return type;
+    }
+
+    public boolean isSingleton() {
+        return false;
+    }
+}

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Resource.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Resource.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Resource.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/Resource.java Thu Aug 14 14:33:46 2008
@@ -19,35 +19,9 @@
 
 import java.util.Properties;
 
-import org.apache.openejb.OpenEJBException;
-import org.springframework.beans.factory.BeanNameAware;
-
-public class Resource implements BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
+public class Resource extends AbstractResourceProvider {
     private String type;
-    private Properties properties;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
-    }
-
-    public String getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String provider) {
-        this.provider = provider;
-    }
+    private final Properties properties = new Properties();
 
     public String getType() {
         return type;
@@ -62,31 +36,7 @@
     }
 
     public void setProperties(Properties properties) {
-        this.properties = properties;
-    }
-
-    public org.apache.openejb.config.sys.Resource getResourceDefinition() throws OpenEJBException {
-        org.apache.openejb.config.sys.Resource resource = new org.apache.openejb.config.sys.Resource();
-
-        if (id != null) {
-            resource.setId(id);
-        } else if (beanName != null) {
-            resource.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for Resource");
-        }
-
-        if (provider != null) {
-            resource.setProvider(provider);
-        }
-
-        if (type != null) {
-            resource.setType(type);
-        }
-        
-        if (properties != null) {
-            resource.getProperties().putAll(properties);
-        }
-        return resource;
+        this.properties.clear();
+        this.properties.putAll(properties);
     }
 }
\ No newline at end of file

Added: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ResourceProvider.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ResourceProvider.java?rev=686050&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ResourceProvider.java (added)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/ResourceProvider.java Thu Aug 14 14:33:46 2008
@@ -0,0 +1,26 @@
+/**
+ *
+ * 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.spring;
+
+import org.apache.openejb.OpenEJBException;
+
+import org.apache.openejb.config.sys.Resource;
+
+public interface ResourceProvider {
+    Resource getResourceDefinition() throws OpenEJBException;
+}

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SingletonContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SingletonContainer.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SingletonContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SingletonContainer.java Thu Aug 14 14:33:46 2008
@@ -17,52 +17,33 @@
  */
 package org.apache.openejb.spring;
 
+import java.util.Properties;
+
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.config.BeanTypes;
 import org.apache.openejb.config.sys.Container;
 import org.springframework.beans.factory.BeanNameAware;
 
-public class SingletonContainer implements ContainerProvider, BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
+public class SingletonContainer extends AbstractContainerProvider {
+    private String accessTimeout;
 
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
+    public String getAccessTimeout() {
+        return accessTimeout;
     }
 
-    public String getProvider() {
-        return provider;
+    public void setAccessTimeout(String accessTimeout) {
+        this.accessTimeout = accessTimeout;
     }
 
-    public void setProvider(String provider) {
-        this.provider = provider;
+    protected String getContainerType() {
+        return BeanTypes.SINGLETON;
     }
 
-    public Container getContainerDefinition() throws OpenEJBException {
-        Container container = new Container();
-        container.setCtype(BeanTypes.SINGLETON);
-
-        if (id != null) {
-            container.setId(id);
-        } else if (beanName != null) {
-            container.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for SingletonContainer");
-        }
-
-        if (provider != null) {
-            container.setProvider(provider);
+    protected Properties getProperties() {
+        Properties properties = new Properties();
+        if (accessTimeout != null) {
+            properties.setProperty("AccessTimeout", accessTimeout);
         }
-
-        return container;
+        return properties;
     }
 }
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringAssembler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringAssembler.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringAssembler.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/SpringAssembler.java Thu Aug 14 14:33:46 2008
@@ -83,7 +83,7 @@
         //
         // Resources
         //
-        for (Resource resource : openEJB.getResources()) {
+        for (ResourceProvider resource : openEJB.getResources()) {
             ResourceInfo info = configurationFactory.configureService(resource.getResourceDefinition(), ResourceInfo.class);
             importedResourceIds.add(info.id);
             configuration.facilities.resources.add(info);

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatefulContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatefulContainer.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatefulContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatefulContainer.java Thu Aug 14 14:33:46 2008
@@ -19,40 +19,14 @@
 
 import java.util.Properties;
 
-import org.springframework.beans.factory.BeanNameAware;
-import org.apache.openejb.config.sys.Container;
 import org.apache.openejb.config.BeanTypes;
-import org.apache.openejb.OpenEJBException;
 
-public class StatefulContainer implements ContainerProvider, BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
+public class StatefulContainer extends AbstractContainerProvider {
     private String passivator;
     private Integer timeOut;
     private Integer poolSize;
     private Integer bulkPassivate;
 
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
-    }
-
-    public String getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String provider) {
-        this.provider = provider;
-    }
-
     public String getPassivator() {
         return passivator;
     }
@@ -85,23 +59,12 @@
         this.bulkPassivate = bulkPassivate;
     }
 
-    public Container getContainerDefinition() throws OpenEJBException {
-        Container container = new Container();
-        container.setCtype(BeanTypes.STATEFUL);
-
-        if (id != null) {
-            container.setId(id);
-        } else if (beanName != null) {
-            container.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for StatefulContainer");
-        }
-
-        if (provider != null) {
-            container.setProvider(provider);
-        }
+    protected String getContainerType() {
+        return BeanTypes.STATEFUL;
+    }
 
-        Properties properties = container.getProperties();
+    protected Properties getProperties() {
+        Properties properties = new Properties();
         if (passivator != null) {
             properties.put("Passivator", passivator);
         }
@@ -114,6 +77,6 @@
         if (bulkPassivate != null) {
             properties.put("BulkPassivate", bulkPassivate);
         }
-        return container;
+        return properties;
     }
 }
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatelessContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatelessContainer.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatelessContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/main/java/org/apache/openejb/spring/StatelessContainer.java Thu Aug 14 14:33:46 2008
@@ -19,40 +19,14 @@
 
 import java.util.Properties;
 
-import org.springframework.beans.factory.BeanNameAware;
-import org.apache.openejb.config.sys.Container;
 import org.apache.openejb.config.BeanTypes;
-import org.apache.openejb.OpenEJBException;
 
-public class StatelessContainer implements ContainerProvider, BeanNameAware {
-    private String id;
-    private String beanName;
-    private String provider;
+public class StatelessContainer extends AbstractContainerProvider {
     private String passivator;
     private Integer timeOut;
     private Integer poolSize;
     private Boolean strictPooling;
 
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public void setBeanName(String beanName) {
-        this.beanName = beanName;
-    }
-
-    public String getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String provider) {
-        this.provider = provider;
-    }
-
     public String getPassivator() {
         return passivator;
     }
@@ -85,23 +59,12 @@
         this.strictPooling = strictPooling;
     }
 
-    public Container getContainerDefinition() throws OpenEJBException {
-        Container container = new Container();
-        container.setCtype(BeanTypes.STATELESS);
-
-        if (id != null) {
-            container.setId(id);
-        } else if (beanName != null) {
-            container.setId(beanName);
-        } else {
-            throw new OpenEJBException("No id defined for StatelessContainer");
-        }
-
-        if (provider != null) {
-            container.setProvider(provider);
-        }
+    protected String getContainerType() {
+        return BeanTypes.STATELESS;
+    }
 
-        Properties properties = container.getProperties();
+    protected Properties getProperties() {
+        Properties properties = new Properties();
         if (passivator != null) {
             properties.put("Passivator", passivator);
         }
@@ -114,6 +77,6 @@
         if (strictPooling != null) {
             properties.put("StrictPooling", strictPooling);
         }
-        return container;
+        return properties;
     }
 }
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-spring/src/test/java/org/apache/openejb/spring/SpringTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/test/java/org/apache/openejb/spring/SpringTest.java?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/test/java/org/apache/openejb/spring/SpringTest.java (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/test/java/org/apache/openejb/spring/SpringTest.java Thu Aug 14 14:33:46 2008
@@ -110,17 +110,20 @@
         assertTrue("cmpContainer should be an instance of CmpContainer", cmpContainer instanceof org.apache.openejb.core.cmp.CmpContainer);
 
         //
-        // ClassPath Application
-        //
-        Application application = (Application) context.getBean("classPathApplication");
-
-        //
         // EJB
         //
-        EJB ejb = (EJB) context.getBean("EchoBean");
+        Echo echo = (Echo) context.getBean("EchoBean");
+        assertNotNull("echo is null", echo);
+        assertEquals("olleH", echo.echo("Hello"));
 
         System.out.println();
         System.out.println();
         Debug.printContext(initialContext);
+
+
+        //
+        // Stop the Spring Context
+        //
+        context.destroy();
     }
 }

Modified: openejb/trunk/openejb3/container/openejb-spring/src/test/resources/org/apache/openejb/spring/spring.xml
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-spring/src/test/resources/org/apache/openejb/spring/spring.xml?rev=686050&r1=686049&r2=686050&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-spring/src/test/resources/org/apache/openejb/spring/spring.xml (original)
+++ openejb/trunk/openejb3/container/openejb-spring/src/test/resources/org/apache/openejb/spring/spring.xml Thu Aug 14 14:33:46 2008
@@ -33,6 +33,7 @@
             <list>
                 <bean class="org.apache.openejb.spring.SingletonContainer">
                     <property name="id" value="Spring Defined SingletonContainer"/>
+                    <property name="accessTimeout" value="45 sec"/>
                 </bean>
                 <bean class="org.apache.openejb.spring.StatelessContainer">
                     <property name="id" value="Spring Defined StatelessContainer"/>
@@ -72,24 +73,32 @@
         </property>
     </bean>
 
+    <!-- Spring declared TransactionManager which is automatically imported -->
     <bean name="tm" class="org.apache.openejb.spring.MockTransactionManager"/>
+
+    <!-- Spring declared SecurityService which is automatically imported -->
     <bean name="sec" class="org.apache.openejb.spring.MockSecurityService"/>
 
+    <!-- Spring declared DataSource which is imported into OpenEJB -->
     <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
         <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
         <property name="url" value="jdbc:hsqldb:file:data/hsqldb/hsqldb"/>
         <property name="username" value="sa"/>
     </bean>
 
+    <!-- An Application containing all EJBs in the classloader -->
     <bean name="classPathApplication" class="org.apache.openejb.spring.Application">
         <property name="openEJB" ref="OpenEJB"/>
     </bean>
 
+    <!-- Deploys the classPathApplication, the EchoBean and return a proxy -->
     <bean name="EchoBean" class="org.apache.openejb.spring.EJB">
         <property name="application" ref="classPathApplication"/>
         <property name="deploymentId" value="EchoBean"/>
+        <property name="interface" value="org.apache.openejb.spring.Echo"/>
     </bean>
 
+    <!-- DataSource exported from OpenEJB -->
     <bean id="openejbDS" class="org.apache.openejb.spring.OpenEJBDataSource" depends-on="OpenEJB">
         <property name="resourceId" value="ds"/>
     </bean>