Author: dblevins
Date: Fri Jul 17 22:24:59 2009
New Revision: 795252

URL: http://svn.apache.org/viewvc?rev=795252&view=rev
Log:
More or less a rewrite of the business interface processing code in conjunction 
with OPENEJB-1039 and other issues discovered when in and out of strict mode.
A large and still growing test case BusinessInterfacesTest validates the new 
logic along with some positive tck feedback.
New code is much easier to follow and far more documented.  Still need to keep 
flushing out the test case.

Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties
    
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java?rev=795252&r1=795251&r2=795252&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
 Fri Jul 17 22:24:59 2009
@@ -160,6 +160,8 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.Collection;
+import java.util.LinkedHashSet;
 
 /**
  * @version $Rev$ $Date$
@@ -1522,22 +1524,69 @@
 
             boolean strict = getProperty(ejbModule, 
STRICT_INTERFACE_DECLARATION, false + "").equalsIgnoreCase("true");
 
+            /*
+             * Collect all interfaces explicitly declared via xml.
+             * We will subtract these from the interfaces implemented
+             * by the bean and do annotation scanning on the remainder.
+             */
+            List<String> descriptor = new ArrayList<String>();
+            descriptor.add(sessionBean.getHome());
+            descriptor.add(sessionBean.getRemote());
+            descriptor.add(sessionBean.getLocalHome());
+            descriptor.add(sessionBean.getLocal());
+            descriptor.addAll(sessionBean.getBusinessLocal());
+            descriptor.addAll(sessionBean.getBusinessRemote());
+            descriptor.add(sessionBean.getServiceEndpoint());
+
+            BusinessInterfaces xml = new BusinessInterfaces();
+            xml.addLocals(sessionBean.getBusinessLocal(), 
ejbModule.getClassLoader());
+            xml.addRemotes(sessionBean.getBusinessRemote(), 
ejbModule.getClassLoader());
+
+            /**
+             * Anything declared as both <business-local> and 
<business-remote> is invalid in strict mode
+             */
+            if (strict) for (Class interfce : xml.local) {
+                if (xml.remote.contains(interfce)) {
+                    validation.fail(ejbName, "xml.localRemote.conflict", 
interfce.getName());
+                }
+            }
+
+            /**
+             * Merge the xml declared business interfaces into the complete set
+             */
+            BusinessInterfaces all = new BusinessInterfaces();
+            all.local.addAll(xml.local);
+            all.remote.addAll(xml.remote);
+
             for (Class<?> clazz : ancestors(beanClass)) {
                 /*
-                 * Collect all interfaces explicitly declared via xml.
-                 * We will subtract these from the interfaces implemented
-                 * by the bean and do annotation scanning on the remainder.
-                 */
-                List<String> xmlDeclared = new ArrayList<String>();
-                xmlDeclared.add(sessionBean.getHome());
-                xmlDeclared.add(sessionBean.getRemote());
-                xmlDeclared.add(sessionBean.getLocalHome());
-                xmlDeclared.add(sessionBean.getLocal());
-
-                if (strict) { // when not being strict, thse
-                    xmlDeclared.addAll(sessionBean.getBusinessLocal());
-                    xmlDeclared.addAll(sessionBean.getBusinessRemote());
-                    xmlDeclared.add(sessionBean.getServiceEndpoint());
+                 * @WebService
+                 * @WebServiceProvider
+                 */
+                if (sessionBean.getServiceEndpoint() == null) {
+                    Class defaultEndpoint = 
DeploymentInfo.ServiceEndpoint.class;
+
+                    for (Class interfce : clazz.getInterfaces()) {
+                        if (interfce.isAnnotationPresent(WebService.class)) {
+                            defaultEndpoint = interfce;
+                        }
+                    }
+
+                    WebService webService = 
clazz.getAnnotation(WebService.class);
+                    if (webService != null) {
+
+                        String className = webService.endpointInterface();
+
+                        if (!className.equals("")) {
+                            sessionBean.setServiceEndpoint(className);
+                        } else {
+                            
sessionBean.setServiceEndpoint(defaultEndpoint.getName());
+                        }
+                    } else if 
(clazz.isAnnotationPresent(WebServiceProvider.class)) {
+                        
sessionBean.setServiceEndpoint(defaultEndpoint.getName());
+                    } else if 
(!defaultEndpoint.equals(DeploymentInfo.ServiceEndpoint.class)) {
+                        
sessionBean.setServiceEndpoint(defaultEndpoint.getName());
+                    }
                 }
 
                 /*
@@ -1552,148 +1601,202 @@
                     if (!name.equals("java.io.Serializable") &&
                             !name.equals("java.io.Externalizable") &&
                             !name.startsWith("javax.ejb.") &&
-                            !xmlDeclared.contains(interfce.getName())) {
+                            !descriptor.contains(interfce.getName())) {
                         interfaces.add(interfce);
                     }
                 }
 
-                List<Class> declared = new ArrayList<Class>();
+                /**
+                 * Anything discovered and delcared in a previous loop
+                 * or at the beginning in the deployment descriptor is
+                 * not eligable to be redefined.
+                 */
+                interfaces.removeAll(all.local);
+                interfaces.removeAll(all.remote);
 
-                /*
-                 * @Remote
+                /**
+                 * OK, now start checking the class metadata
                  */
-                List<Class> remotes = new ArrayList<Class>();
+                Local local = clazz.getAnnotation(Local.class);
                 Remote remote = clazz.getAnnotation(Remote.class);
-                if (remote != null) {
-                    if (remote.value().length == 0) {
-                        if (interfaces.size() != 1) {
-                            validation.fail(ejbName, 
"ann.remote.noAttributes", join(", ", interfaces));
-                        } else if (strict && clazz.getAnnotation(Local.class) 
!= null) {
-                            validation.fail(ejbName, 
"ann.remoteLocal.ambiguous", join(", ", interfaces));
-                        } else if (strict && 
interfaces.get(0).getAnnotation(Local.class) != null) {
-                            validation.fail(ejbName, 
"ann.remoteLocal.conflict", join(", ", interfaces));
-                        } else {
-                            if (validateRemoteInterface(interfaces.get(0), 
validation, ejbName)) {
-                                remotes.add(interfaces.get(0));
-                            }
-                            declared.add(interfaces.get(0));
-                        }
-                    } else for (Class interfce : remote.value()) {
-                        if (validateRemoteInterface(interfce, validation, 
ejbName)) {
-                            remotes.add(interfce);
-                        }
-                        declared.add(interfce);
+
+                boolean impliedLocal = local != null && local.value().length 
== 0;
+                boolean impliedRemote = remote != null && 
remote.value().length == 0;
+
+                /**
+                 * This set holds the values of @Local and @Remote
+                 * when applied to the bean class itself
+                 *
+                 * These declarations override any similar declaration
+                 * on the interface.
+                 */
+                BusinessInterfaces bean = new BusinessInterfaces();
+                if (local != null) bean.local.addAll(asList(local.value()));
+                if (remote != null) bean.remote.addAll(asList(remote.value()));
+
+                if (strict) for (Class interfce : bean.local) {
+                    if (bean.remote.contains(interfce)) {
+                        validation.fail(ejbName, "ann.localRemote.conflict", 
interfce.getName());
                     }
                 }
 
-                if (strict) interfaces.removeAll(declared);
-                
-                /*
-                 * @Local
-                 */
-                List<Class> locals = new ArrayList<Class>();
-                Local local = clazz.getAnnotation(Local.class);
-                if (local != null) {
-                    if (local.value().length == 0) {
-                        if (interfaces.size() != 1) {
-                            validation.fail(ejbName, "ann.local.noAttributes", 
join(", ", interfaces));
-                        } else if (strict && clazz.getAnnotation(Remote.class) 
!= null) {
-                            validation.fail(ejbName, 
"ann.localRemote.ambiguous", join(", ", interfaces));
-                        } else if (strict && 
interfaces.get(0).getAnnotation(Remote.class) != null) {
-                            validation.fail(ejbName, 
"ann.localRemote.conflict", join(", ", interfaces));
+                /**
+                 * Anything listed explicitly via @Local or @Remote
+                 * on the bean class does not need to be investigated.
+                 * We do not need to check these interfaces for @Local or 
@Remote
+                 */
+                interfaces.removeAll(bean.local);
+                interfaces.removeAll(bean.remote);
+
+                if (impliedLocal || impliedRemote) {
+                    if (interfaces.size() == 1) {
+                        Class<?> interfce = interfaces.remove(0);
+
+                        if (strict && impliedLocal && impliedRemote) {
+                            /**
+                             * Cannot imply @Local and @Remote at the same 
time with strict mode on
+                             */
+                            validation.fail(ejbName, 
"ann.localRemote.ambiguous", interfce.getName());
                         } else {
-                            if (validateLocalInterface(interfaces.get(0), 
validation, ejbName)) {
-                                locals.add(interfaces.get(0));
-                            }
-                            declared.add(interfaces.get(0));
+                            if (impliedLocal) bean.local.add(interfce);
+                            if (impliedRemote) bean.remote.add(interfce);
                         }
-                    } else for (Class interfce : local.value()) {
-                        if (validateLocalInterface(interfce, validation, 
ejbName)) {
-                            locals.add(interfce);
-                        }
-                        declared.add(interfce);
-                    }
-                }
 
-                if (strict) interfaces.removeAll(declared);
+                    } else { // invalid
+                        /**
+                         * Cannot imply either @Local or @Remote and list 
multiple interfaces
+                         */
+                        if (impliedLocal) validation.fail(ejbName, 
"ann.local.noAttributes", join(", ", interfaces));
+                        if (impliedRemote) validation.fail(ejbName, 
"ann.remote.noAttributes", join(", ", interfaces));
 
-                /*
-                 * @WebService
-                 * @WebServiceProvider
-                 */
-                if (sessionBean.getServiceEndpoint() == null) {
-                    WebService webService = 
clazz.getAnnotation(WebService.class);
-                    if (webService != null) {
-                        String endpointInterfaceName = 
webService.endpointInterface();
-                        if (!endpointInterfaceName.equals("")) {
-                            try {
-                                
sessionBean.setServiceEndpoint(endpointInterfaceName);
-                                Class endpointInterface = 
Class.forName(endpointInterfaceName, false, ejbModule.getClassLoader());
-                                declared.add(endpointInterface);
-                            } catch (ClassNotFoundException e) {
-                                throw new IllegalStateException("Class not 
found @WebService.endpointInterface: " + endpointInterfaceName, e);
-                            }
-                        } else {
-                            
sessionBean.setServiceEndpoint(DeploymentInfo.ServiceEndpoint.class.getName());
-                        }
-                    } else if 
(clazz.isAnnotationPresent(WebServiceProvider.class)) {
-                        
sessionBean.setServiceEndpoint(DeploymentInfo.ServiceEndpoint.class.getName());
+                        /**
+                         * This bean is invalid, so do not bother looking at 
the other interfaces or the superclass
+                         */
+                        return;
                     }
                 }
 
-                if (strict) interfaces.removeAll(declared);
 
-                /*
-                 * The remainder of the interfaces are checked for annotations 
in this order:
-                 * 1. @WebService
-                 * 2. @Remote
-                 * 3. Else assumed to be @Local
+                /**
+                 * OK, now start checking the metadata of the interfaces 
implemented by this class
                  */
-                for (Class interfce : interfaces) {
-                    if (interfce.isAnnotationPresent(WebService.class)) {
-                        if (sessionBean.getServiceEndpoint() == null){
-                            sessionBean.setServiceEndpoint(interfce.getName());
-                        } else if 
(sessionBean.getServiceEndpoint().equals(DeploymentInfo.ServiceEndpoint.class.getName()))
 {
-                            sessionBean.setServiceEndpoint(interfce.getName());
-                        }
-                        declared.add(interfce);
-                    }
-                }
+            
 
-                if (strict) interfaces.removeAll(declared);
+                /**
+                 * This set holds the list of interfaces that the bean 
implements
+                 * that are annotated either as @Local or @Remote
+                 *
+                 * If the interface is annotated to the contrary in the bean 
class
+                 * the bean class meta data wins, therefore we track these 
separately
+                 *
+                 * Ultimately, the deployment descriptor wins over all, so we 
have tracked
+                 * those declarations separately as well.
+                 */
+                BusinessInterfaces implemented = new BusinessInterfaces();
 
                 for (Class interfce : interfaces) {
-                    if (interfce.isAnnotationPresent(Remote.class)) {
-                        remotes.add(interfce);
-                        declared.add(interfce);
+                    boolean isLocal = 
interfce.isAnnotationPresent(Local.class);
+                    boolean isRemote = 
interfce.isAnnotationPresent(Remote.class);
+
+                    if (strict && isLocal && isRemote) {
+                        validation.fail(ejbName, "ann.localRemote.conflict", 
interfce.getName());
+                    } else {
+                        if (isLocal) implemented.local.add(interfce);
+                        if (isRemote) implemented.remote.add(interfce);
                     }
                 }
 
-                if (strict) interfaces.removeAll(declared);
+                interfaces.removeAll(implemented.local);
+                interfaces.removeAll(implemented.remote);
 
-                for (Class interfce : interfaces) {
-                    if (interfce.isAnnotationPresent(Local.class)) {
-                        locals.add(interfce);
-                        declared.add(interfce);
-                    }
-                }
 
-                if (!strict){
-                    // Treat the rest of the unannotated and undeclared 
interfaces implicitly as local interfaces
-                    interfaces.removeAll(declared);
-                    locals.addAll(interfaces);
-                }
 
                 /**
-                 * The 'interfaces' list should now be empty and all interfaces
-                 * of the bean sorted into either the remote or local bucket.
+                 * Merge in class-level metadata.
+                 *
+                 * We've already merged in the xml metadata, so that
+                 * metadata will win over this metadata.
+                 */
+
+                // remove anything we've already seen
+                bean.local.removeAll(all.local);
+                bean.local.removeAll(all.remote);
+                bean.remote.removeAll(all.remote);
+                bean.remote.removeAll(all.local);
+
+                // validate the things we are going to add
+                for (Class interfce : bean.local) 
validateLocalInterface(interfce, validation, ejbName);
+                for (Class interfce : bean.remote) 
validateRemoteInterface(interfce, validation, ejbName);
+
+                // add finally, add them
+                all.local.addAll(bean.local);
+                all.remote.addAll(bean.remote);
+
+
+                /**
+                 * Merge in interface-level metadata
+                 *
+                 * We've already merged in the xml metadata *and* class 
metadata,
+                 * so both of those will win over this metadata.
+                 */
+
+                // remove anything we've already seen
+                implemented.local.removeAll(all.local);
+                implemented.local.removeAll(all.remote);
+                implemented.remote.removeAll(all.remote);
+                implemented.remote.removeAll(all.local);
+
+                // validate the things we are going to add
+                for (Class interfce : implemented.local) 
validateLocalInterface(interfce, validation, ejbName);
+                for (Class interfce : implemented.remote) 
validateRemoteInterface(interfce, validation, ejbName);
+
+                // add the rest
+                all.local.addAll(implemented.local);
+                all.remote.addAll(implemented.remote);
+
+
+                /**
+                 * Track any interfaces we didn't use
                  */
-                for (Class interfce : remotes) {
-                    sessionBean.addBusinessRemote(interfce.getName());
-                }
+                all.unspecified.addAll(interfaces);
+            }
+
+            // Finally, add all the business interfaces we found
+            for (Class interfce : all.local) 
sessionBean.addBusinessLocal(interfce);
+            for (Class interfce : all.remote) 
sessionBean.addBusinessRemote(interfce);
 
-                for (Class interfce : locals) {
-                    sessionBean.addBusinessLocal(interfce.getName());
+            // Anything unspecified?  Let's throw it in as local.
+            //
+            // This covers the required case where a bean is declared 
implementing
+            // one interface and does not use @Local or @Remote anywhere nor 
does
+            // it specify the business-local or business-remote elements in 
the ejb-jar.xml
+            //
+            // It goes a little beyond that, but no one has ever complained 
about having
+            // more local interfaces.
+            for (Class interfce : all.unspecified) 
sessionBean.addBusinessLocal(interfce);
+
+        }
+
+        private static class BusinessInterfaces {
+            private Set<Class> local = new LinkedHashSet<Class>();
+            private Set<Class> remote = new LinkedHashSet<Class>();
+            private Set<Class> unspecified = new LinkedHashSet<Class>();
+
+            public void addLocals(Collection<String> names, ClassLoader 
loader){
+                add(loader, names, local);
+            }
+
+            public void addRemotes(Collection<String> names, ClassLoader 
loader){
+                add(loader, names, remote);
+            }
+
+            private void add(ClassLoader loader, Collection<String> names, 
Set<Class> classes) {
+                for (String className : names) {
+                    try {
+                        classes.add(loader.loadClass(className));
+                    } catch (Throwable t) {
+                        // handled in validation
+                    }
                 }
             }
         }

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties?rev=795252&r1=795251&r2=795252&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties
 Fri Jul 17 22:24:59 2009
@@ -255,6 +255,11 @@
 3.injectionTarget.nameContainsSet = The injection-target-name "{0}" for setter 
methods should not begin with "set".  The last portion of the name "{1}" has 
been automatically corrected to "{2}".  Update the descriptor with the correct 
injection-target-name of "{3}" to avoid receiving this warning.  Resource to be 
injected is "{4}".
 
 # AnnotationDeployer.java
+# fail(ejbName, "xml.localRemote.conflict", interfce);
+1.xml.localRemote.conflict = Interface illegally declared as both 
<business-local> and <business-remote>.
+2.xml.localRemote.conflict = Interface illegally declared as both 
<business-local> and <business-remote>: {0}
+3.xml.localRemote.conflict = When declaring business interface as 
<business-local> in an ejb-jar.xml file, the same interface cannot be listed as 
<business-remote>.  Revise the declaration of business interface "{0}" so that 
it is either local or remote, not both.
+
 # fail(ejbName, "ann.remote.noAttributes", join(", ", interfaces));
 1.ann.remote.noAttributes = Ambiguous @Remote() usage on bean class
 2.ann.remote.noAttributes = Ambiguous @Remote() usage on bean class.  Must 
list interfaces explicitly in annotation.
@@ -263,7 +268,7 @@
 # fail(ejbName, "ann.remoteLocal.ambiguous", join(", ", interfaces));
 1.ann.remoteLocal.ambiguous = Ambiguous @Remote and @Local usage on bean class.
 2.ann.remoteLocal.ambiguous = Ambiguous @Remote and @Local usage on bean 
class.  Must list interfaces explicitly in @Remote annotation.
-3.ann.remoteLocal.ambiguous = When annotating a bean class as @Remote with no 
annotation attributes you must not also annotate it with @Local.  List the 
remote interfaces explicitly in the annotation, such as @Remote(\{{0}\}).  
Alternatively, apply the @Remote annotation to the individual interfaces and 
remove it from the bean class.
+3.ann.remoteLocal.ambiguous = When annotating a bean class as @Remote with no 
annotation attributes you must not also annotate it with @Local with no 
attributes.  List the remote interfaces explicitly in the annotation, such as 
@Remote(\{{0}\}).  Alternatively, apply the @Remote annotation to the 
individual interfaces and remove it from the bean class.
 
 # fail(ejbName, "ann.remoteLocal.conflict", join(", ", interfaces));
 1.ann.remoteLocal.conflict = @Remote annotation in bean class conflicts with 
@Local in interface.

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java?rev=795252&r1=795251&r2=795252&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/BusinessInterfacesTest.java
 Fri Jul 17 22:24:59 2009
@@ -1,5 +1,5 @@
 /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
+ * Licensed to the Apache Software Foundation (ASF) under Local 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
@@ -17,15 +17,14 @@
 package org.apache.openejb.config;
 
 import junit.framework.TestCase;
-import org.apache.openejb.assembler.classic.Assembler;
 import org.apache.openejb.assembler.classic.EjbJarInfo;
 import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
-import org.apache.openejb.assembler.classic.SecurityServiceInfo;
-import org.apache.openejb.assembler.classic.TransactionServiceInfo;
-import org.apache.openejb.client.LocalInitialContextFactory;
+import org.apache.openejb.assembler.classic.Assembler;
 import org.apache.openejb.jee.EjbJar;
 import org.apache.openejb.jee.StatelessBean;
-import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.jee.oejb3.OpenejbJar;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.config.rules.ValidationAssertions;
 
 import javax.ejb.Local;
 import javax.ejb.Remote;
@@ -34,138 +33,397 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Arrays;
+import java.io.Serializable;
 
 public class BusinessInterfacesTest extends TestCase {
 
-    public void test() throws Exception {
+    private ConfigurationFactory config;
+    private EjbModule ejbModule;
+    private EjbJar ejbJar;
+
+    @Override
+    protected void setUp() throws Exception {
+        Assembler assembler = new Assembler();
+        config = new ConfigurationFactory();
+
+        ejbModule = new EjbModule(new EjbJar());
+        ejbModule.setOpenejbJar(new OpenejbJar());
+        ejbJar = ejbModule.getEjbJar();
+
+        strict(false);
+    }
+
+    private void strict(boolean b) {
+        
ejbModule.getOpenejbJar().getProperties().setProperty("openejb.strict.interface.declaration",
 b +"");
     }
 
-    public void _testDefault() throws Exception {
-        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, 
LocalInitialContextFactory.class.getName());
+    private Map<String, EnterpriseBeanInfo> deploy(Class<?>... beans) throws 
OpenEJBException {
+        for (Class<?> bean : beans) {
+            addBean(bean);
+        }
+        EjbJarInfo ejbJarInfo = config.configureApplication(ejbModule);
 
-        ConfigurationFactory config = new ConfigurationFactory();
-        Assembler assembler = new Assembler();
+        return asMap(ejbJarInfo.enterpriseBeans);
+    }
+
+    private StatelessBean addBean(Class<?> orangeBeanClass) {
+        return ejbJar.addEnterpriseBean(new StatelessBean(orangeBeanClass));
+    }
+
+    // 
----------------------------------------------------------------------------------------------------------------
+    //  Yellow
+    // 
----------------------------------------------------------------------------------------------------------------
+
+    public static interface YellowOneLocal {
+    }
+
+    @Local
+    public static class YellowOneBean implements YellowOneLocal, Serializable {
+    }
+
+    // - - -
+
+    public static interface YellowTwoRemote {
+    }
+
+    @Remote
+    public static class YellowTwoBean implements YellowTwoRemote, Serializable 
{
+    }
+
+    // - - -
+
+    public static interface YellowThreeUnspecified {
+    }
+
+    public static class YellowThreeBean implements YellowThreeUnspecified, 
Serializable {
+    }
 
-        
SystemInstance.get().setProperty("openejb.strict.interface.declaration", 
"false");
+    // - - -
 
-        
assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
-        
assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+    @Local
+    public static interface YellowFourLocal {
+    }
+
+    public static class YellowFourBean implements YellowFourLocal, 
Serializable {
+    }
 
-        EjbJar ejbJar = new EjbJar();
-        ejbJar.addEnterpriseBean(new StatelessBean(OrangeBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(RedBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(YellowBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(GreenBean.class));
+    // - - -
 
-        StatelessBean white = ejbJar.addEnterpriseBean(new 
StatelessBean(WhiteBean.class));
-        white.addBusinessLocal(WhiteOne.class);
-        white.addBusinessLocal(WhiteThree.class);
+    @Remote
+    public static interface YellowFiveRemote {
+    }
 
-        StatelessBean black = ejbJar.addEnterpriseBean(new 
StatelessBean(BlackBean.class));
-        black.addBusinessRemote(BlackTwo.class);
-        black.addBusinessRemote(BlackThree.class);
+    public static class YellowFiveBean implements YellowFiveRemote, 
Serializable {
+    }
 
-        ejbJar.addEnterpriseBean(new StatelessBean(MagentaBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(CyanBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(PurpleBean.class));
+    public void testYellow() throws Exception {
+        // Results should be the same with strict on or off
+        for (boolean strict : Arrays.asList(false, true)) {
+            setUp();
+            strict(strict);
 
-        EjbJarInfo ejbJarInfo = config.configureApplication(ejbJar);
+            Map<String, EnterpriseBeanInfo> beans = 
deploy(YellowOneBean.class, YellowTwoBean.class, YellowThreeBean.class, 
YellowFourBean.class, YellowFiveBean.class);
 
-        Map<String, EnterpriseBeanInfo> beans = 
asMap(ejbJarInfo.enterpriseBeans);
+            EnterpriseBeanInfo beanInfo;
 
-        EnterpriseBeanInfo beanInfo = beans.get("OrangeBean");
+            beanInfo = beans.get("YellowOneBean");
 
-        assertEquals(list(OrangeOne.class, OrangeThree.class, 
OrangeFour.class), sort(beanInfo.businessLocal));
-        assertEquals(list(OrangeTwo.class, OrangeThree.class), 
sort(beanInfo.businessRemote));
+            assertEquals(list(YellowOneLocal.class), 
sort(beanInfo.businessLocal));
+            assertEquals(list(), sort(beanInfo.businessRemote));
 
-        beanInfo = beans.get("RedBean");
+            beanInfo = beans.get("YellowTwoBean");
 
-        assertEquals(list(RedOne.class, RedThree.class, RedFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(RedTwo.class, RedThree.class), 
sort(beanInfo.businessRemote));
+            assertEquals(list(), sort(beanInfo.businessLocal));
+            assertEquals(list(YellowTwoRemote.class), 
sort(beanInfo.businessRemote));
 
-        beanInfo = beans.get("YellowBean");
+            beanInfo = beans.get("YellowThreeBean");
 
-        assertEquals(list(YellowOne.class, YellowThree.class, 
YellowFour.class), sort(beanInfo.businessLocal));
-        assertEquals(list(YellowTwo.class, YellowThree.class), 
sort(beanInfo.businessRemote));
+            assertEquals(list(YellowThreeUnspecified.class), 
sort(beanInfo.businessLocal));
+            assertEquals(list(), sort(beanInfo.businessRemote));
 
-        beanInfo = beans.get("GreenBean");
+            beanInfo = beans.get("YellowFourBean");
 
-        assertEquals(list(GreenOne.class, GreenThree.class, GreenFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(GreenTwo.class, GreenThree.class), 
sort(beanInfo.businessRemote));
+            assertEquals(list(YellowFourLocal.class), 
sort(beanInfo.businessLocal));
+            assertEquals(list(), sort(beanInfo.businessRemote));
 
-        beanInfo = beans.get("WhiteBean");
+            beanInfo = beans.get("YellowFiveBean");
 
-        assertEquals(list(WhiteOne.class, WhiteThree.class, WhiteFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(WhiteTwo.class, WhiteThree.class), 
sort(beanInfo.businessRemote));
+            assertEquals(list(), sort(beanInfo.businessLocal));
+            assertEquals(list(YellowFiveRemote.class), 
sort(beanInfo.businessRemote));
 
-        beanInfo = beans.get("BlackBean");
+        }
+    }
 
-        assertEquals(list(BlackOne.class, BlackThree.class, BlackFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(BlackTwo.class, BlackThree.class), 
sort(beanInfo.businessRemote));
+    // 
----------------------------------------------------------------------------------------------------------------
+    //  InvalidYellow
+    // 
----------------------------------------------------------------------------------------------------------------
 
+    public static interface InvalidYellowOneLocal {
     }
 
-    public void _testStrict() throws Exception {
-        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, 
LocalInitialContextFactory.class.getName());
+    public static interface InvalidYellowOneLocal2 {
+    }
 
-        ConfigurationFactory config = new ConfigurationFactory();
-        Assembler assembler = new Assembler();
+    @Local
+    public static class InvalidYellowOneBean implements InvalidYellowOneLocal, 
InvalidYellowOneLocal2, Serializable {
+    }
+
+    // - - -
+
+    public static interface InvalidYellowTwoRemote {
+    }
+
+    public static interface InvalidYellowTwoRemote2 {
+    }
+
+    @Remote
+    public static class InvalidYellowTwoBean implements 
InvalidYellowTwoRemote, InvalidYellowTwoRemote2, Serializable {
+    }
+
+    // - - -
+
+    public static interface InvalidYellowThreeUnspecified {
+    }
+
+    public static interface InvalidYellowThreeUnspecified2 {
+    }
+
+    public static class InvalidYellowThreeBean implements 
InvalidYellowThreeUnspecified, InvalidYellowThreeUnspecified2, Serializable {
+    }
+
+    //TODO this test fails becuse the error message formatting support has an 
issue with escaping like \{
+    // we really need to fix that
+    public void _testInvalidYellow() throws Exception {
+        // Results should be the same with strict on or off
+        for (boolean strict : Arrays.asList(false, true)) {
+            setUp();
+            strict(strict);
+
+            List<String> expectedKeys = new ArrayList<String>();
+            expectedKeys.add("ann.local.noAttributes");
+            expectedKeys.add("ann.remote.noAttributes");
+            expectedKeys.add("noInterfaceDeclared.session");
+            expectedKeys.add("noInterfaceDeclared.session");
+
+            try {
+                deploy(InvalidYellowOneBean.class, InvalidYellowTwoBean.class, 
InvalidYellowThreeBean.class);
+            } catch (ValidationFailedException e) {
+                ValidationAssertions.assertFailures(expectedKeys, e);
+            }
+        }
+    }
+
+
+    // 
----------------------------------------------------------------------------------------------------------------
+    //  Green
+    // 
----------------------------------------------------------------------------------------------------------------
+
+    public static interface GreenOneLocal {
+    }
+
+
+    public static interface GreenOneRemote {
+    }
+
+    @Local
+    @Remote(GreenOneRemote.class)
+    public static class GreenOneBean implements GreenOneLocal, GreenOneRemote {
+    }
+
+    // - - -
+
+    public static interface GreenTwoLocal {
+    }
+
+
+    public static interface GreenTwoRemote {
+    }
+
+    @Local(GreenTwoLocal.class)
+    @Remote
+    public static class GreenTwoBean implements GreenTwoLocal, GreenTwoRemote {
+    }
+
+    public void testGreen() throws Exception {
+        // Results should be the same with strict on or off
+        for (boolean strict : Arrays.asList(false, true)) {
+            setUp();
+            strict(strict);
+
+            Map<String, EnterpriseBeanInfo> beans = deploy(GreenOneBean.class, 
GreenTwoBean.class);
+
+            EnterpriseBeanInfo beanInfo;
+
+            beanInfo = beans.get("GreenOneBean");
+
+            assertEquals(list(GreenOneLocal.class), 
sort(beanInfo.businessLocal));
+            assertEquals(list(GreenOneRemote.class), 
sort(beanInfo.businessRemote));
+
+            beanInfo = beans.get("GreenTwoBean");
+
+            assertEquals(list(GreenTwoLocal.class), 
sort(beanInfo.businessLocal));
+            assertEquals(list(GreenTwoRemote.class), 
sort(beanInfo.businessRemote));
+        }
+    }
+
+    // 
----------------------------------------------------------------------------------------------------------------
+    //  Orange
+    // 
----------------------------------------------------------------------------------------------------------------
+
+    @Local
+    public static interface OrangeOneLocal {
+    }
+
+    @Remote
+    public static interface OrangeOneRemote {
+    }
+
+    @Local
+    @Remote
+    public static interface OrangeOneBoth {
+    }
+
+    public static interface OrangeOneUnspecified {
+    }
+
+    public static class OrangeOneBean implements OrangeOneLocal, 
OrangeOneRemote, OrangeOneBoth, OrangeOneUnspecified {
+    }
+
+    // - - -
+
+    public static interface OrangeTwoLocal {
+    }
+
+    public static interface OrangeTwoRemote {
+    }
+
+    public static interface OrangeTwoBoth {
+    }
+
+    public static interface OrangeTwoUnspecified {
+    }
+
+    @Local({OrangeTwoLocal.class, OrangeTwoBoth.class})
+    @Remote({OrangeTwoRemote.class, OrangeTwoBoth.class})
+    public static class OrangeTwoBean implements OrangeTwoLocal, 
OrangeTwoRemote, OrangeTwoBoth, OrangeTwoUnspecified {
+    }
+
+    public void testOrangeNotStrict() throws Exception {
+        strict(false);
+
+        Map<String, EnterpriseBeanInfo> beans = deploy(OrangeOneBean.class, 
OrangeTwoBean.class);
+
+        EnterpriseBeanInfo beanInfo = beans.get("OrangeOneBean");
+
+        assertEquals(list(OrangeOneLocal.class, OrangeOneBoth.class, 
OrangeOneUnspecified.class), sort(beanInfo.businessLocal));
+        assertEquals(list(OrangeOneRemote.class, OrangeOneBoth.class), 
sort(beanInfo.businessRemote));
+
+        beanInfo = beans.get("OrangeTwoBean");
+
+        assertEquals(list(OrangeTwoLocal.class, OrangeTwoBoth.class, 
OrangeTwoUnspecified.class), sort(beanInfo.businessLocal));
+        assertEquals(list(OrangeTwoRemote.class, OrangeTwoBoth.class), 
sort(beanInfo.businessRemote));
+    }
+
+    public void testOrangeStrict() throws Exception {
+        strict(true);
+
+        List<String> expectedKeys = new ArrayList<String>();
+        expectedKeys.add("ann.localRemote.conflict");
+        expectedKeys.add("ann.localRemote.conflict");
+
+        try {
+            deploy(OrangeOneBean.class, OrangeTwoBean.class);
+        } catch (ValidationFailedException e) {
+            ValidationAssertions.assertFailures(expectedKeys, e);
+        }
+    }
+
+
+    // 
----------------------------------------------------------------------------------------------------------------
+    //  Red
+    // 
----------------------------------------------------------------------------------------------------------------
+
+    @Local
+    public static interface RedOneLocal {
+    }
+
+    public static interface RedOneRemote {
+    }
 
-        
SystemInstance.get().setProperty("openejb.strict.interface.declaration", 
"true");
+    @Local
+    public static interface RedOneOverridden {
+    }
 
-        
assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
-        
assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+    public static interface RedOneUnspecified {
+    }
 
-        EjbJar ejbJar = new EjbJar();
-        ejbJar.addEnterpriseBean(new StatelessBean(OrangeBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(RedBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(YellowBean.class));
-        ejbJar.addEnterpriseBean(new StatelessBean(GreenBean.class));
+    @Remote({RedOneRemote.class, RedOneOverridden.class})
+    public static class RedOneBean implements RedOneLocal, RedOneRemote, 
RedOneOverridden, RedOneUnspecified {
+    }
+
+    // - - -
 
-        StatelessBean white = ejbJar.addEnterpriseBean(new 
StatelessBean(WhiteBean.class));
-        white.addBusinessLocal(WhiteOne.class);
-        white.addBusinessLocal(WhiteThree.class);
+    public static interface RedTwoLocal {
+    }
 
-        StatelessBean black = ejbJar.addEnterpriseBean(new 
StatelessBean(BlackBean.class));
-        black.addBusinessRemote(BlackTwo.class);
-        black.addBusinessRemote(BlackThree.class);
+    @Remote
+    public static interface RedTwoRemote {
+    }
 
-        EjbJarInfo ejbJarInfo = config.configureApplication(ejbJar);
+    @Remote
+    public static interface RedTwoOverridden {
+    }
 
-        Map<String, EnterpriseBeanInfo> beans = 
asMap(ejbJarInfo.enterpriseBeans);
+    public static interface RedTwoUnspecified {
+    }
 
-        EnterpriseBeanInfo beanInfo = beans.get("OrangeBean");
+    @Local({RedTwoLocal.class, RedTwoOverridden.class})
+    public static class RedTwoBean implements RedTwoLocal, RedTwoRemote, 
RedTwoOverridden, RedTwoUnspecified {
+    }
 
-        assertEquals(list(OrangeOne.class, OrangeThree.class, 
OrangeFour.class), sort(beanInfo.businessLocal));
-        assertEquals(list(OrangeTwo.class, OrangeThree.class), 
sort(beanInfo.businessRemote));
+    /**
+     * Definition in the bean class wins over the 
+     * @throws Exception
+     */
+    public void testRedNotStrict() throws Exception {
+        strict(false);
 
-        beanInfo = beans.get("RedBean");
+        Map<String, EnterpriseBeanInfo> beans = deploy(RedOneBean.class, 
RedTwoBean.class);
 
-        assertEquals(list(RedOne.class, RedThree.class, RedFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(RedTwo.class, RedThree.class), 
sort(beanInfo.businessRemote));
+        EnterpriseBeanInfo beanInfo = beans.get("RedOneBean");
 
-        beanInfo = beans.get("YellowBean");
+        assertEquals(list(RedOneLocal.class, RedOneUnspecified.class), 
sort(beanInfo.businessLocal));
+        assertEquals(list(RedOneRemote.class, RedOneOverridden.class), 
sort(beanInfo.businessRemote));
 
-        assertEquals(list(YellowOne.class, YellowThree.class, 
YellowFour.class), sort(beanInfo.businessLocal));
-        assertEquals(list(YellowTwo.class, YellowThree.class), 
sort(beanInfo.businessRemote));
+        beanInfo = beans.get("RedTwoBean");
 
-        beanInfo = beans.get("GreenBean");
+        assertEquals(list(RedTwoLocal.class, RedTwoOverridden.class, 
RedTwoUnspecified.class), sort(beanInfo.businessLocal));
+        assertEquals(list(RedTwoRemote.class), sort(beanInfo.businessRemote));
+    }
 
-        assertEquals(list(GreenOne.class, GreenThree.class, GreenFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(GreenTwo.class, GreenThree.class), 
sort(beanInfo.businessRemote));
+    /**
+     * Test results should be the same as above.
+     * 
+     * @throws Exception
+     */
+    public void testRedStrict() throws Exception {
+        strict(true);
 
-        beanInfo = beans.get("WhiteBean");
+        Map<String, EnterpriseBeanInfo> beans = deploy(RedOneBean.class, 
RedTwoBean.class);
 
-        assertEquals(list(WhiteOne.class, WhiteThree.class, WhiteFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(WhiteTwo.class, WhiteThree.class), 
sort(beanInfo.businessRemote));
+        EnterpriseBeanInfo beanInfo = beans.get("RedOneBean");
 
-        beanInfo = beans.get("BlackBean");
+        assertEquals(list(RedOneLocal.class, RedOneUnspecified.class), 
sort(beanInfo.businessLocal));
+        assertEquals(list(RedOneRemote.class, RedOneOverridden.class), 
sort(beanInfo.businessRemote));
 
-        assertEquals(list(BlackOne.class, BlackThree.class, BlackFour.class), 
sort(beanInfo.businessLocal));
-        assertEquals(list(BlackTwo.class, BlackThree.class), 
sort(beanInfo.businessRemote));
+        beanInfo = beans.get("RedTwoBean");
 
+        assertEquals(list(RedTwoLocal.class, RedTwoOverridden.class, 
RedTwoUnspecified.class), sort(beanInfo.businessLocal));
+        assertEquals(list(RedTwoRemote.class), sort(beanInfo.businessRemote));
     }
 
+
     private <T extends Comparable<? super T>> List<T> sort(List<T> list) {
         Collections.sort(list);
         return list;
@@ -189,161 +447,249 @@
     }
 
 
-    // OrangeBean 
----------------------------------------------------------------
+    // RedBean ----------------------------------------------------------------
+
+    // Interfaces == @Local
+    // Bean Class == @Remote
+
+    // Opposite scenario is GreenBean
 
     @Local
-    public static interface OrangeOne {
+    public static interface RedLocal {
     }
 
-    @Remote
-    public static interface OrangeTwo {
+    public static interface RedRemote {
     }
 
     @Local
-    @Remote
-    public static interface OrangeThree {
+    public static interface RedBoth {
     }
 
-    public static interface OrangeFour {
+    public static interface RedUnspecified {
     }
 
-    public static class OrangeBean implements OrangeOne, OrangeTwo, 
OrangeThree, OrangeFour {
+    @Remote({RedRemote.class, RedBoth.class})
+    public static class RedBean implements RedLocal, RedRemote, RedBoth, 
RedUnspecified {
     }
 
-    // RedBean ----------------------------------------------------------------
+    // GreenBean 
----------------------------------------------------------------
 
-    @Local
-    public static interface RedOne {
+    // Interfaces == @Remote
+    // Bean Class == @Local
+
+    // Green is opposite of Red
+
+    public static interface GreenLocal {
     }
 
     @Remote
-    public static interface RedTwo {
+    public static interface GreenRemote {
     }
 
-    @Local
     @Remote
-    public static interface RedThree {
+    public static interface GreenBoth {
     }
 
-    public static interface RedFour {
+    public static interface GreenUnspecified {
     }
 
-    @Local({RedOne.class, RedThree.class})
-    @Remote({RedTwo.class, RedThree.class})
-    public static class RedBean implements RedOne, RedTwo, RedThree, RedFour {
+    @Local({GreenLocal.class, GreenBoth.class})
+    public static class GreenBean implements GreenLocal, GreenRemote, 
GreenBoth, GreenUnspecified {
     }
 
     // YellowBean 
----------------------------------------------------------------
 
-    @Local
-    public static interface YellowOne {
+    // Interfaces == @Local
+    // Bean Class == @Remote
+
+    // Opposite scenario is PurpleBean
+
+    public static interface YellowLocal {
     }
 
-    public static interface YellowTwo {
+    public static interface YellowRemote {
     }
 
     @Local
-    public static interface YellowThree {
+    @Remote
+    public static interface YellowBoth {
     }
 
-    public static interface YellowFour {
+    public static interface YellowUnspecified {
     }
 
-    @Remote({YellowTwo.class, YellowThree.class})
-    public static class YellowBean implements YellowOne, YellowTwo, 
YellowThree, YellowFour {
+    @Local(YellowLocal.class)
+    @Remote(YellowRemote.class)
+    public static class YellowBean implements YellowLocal, YellowRemote, 
YellowBoth, YellowUnspecified {
     }
 
-    // GreenBean 
----------------------------------------------------------------
+    // PurpleBean 
----------------------------------------------------------------
+
+    // Interfaces == @Remote
+    // Bean Class == @Local
+
+    // Purple is opposite of Yellow
 
-    public static interface GreenOne {
+    @Local
+    public static interface PurpleLocal {
     }
 
     @Remote
-    public static interface GreenTwo {
+    public static interface PurpleRemote {
     }
 
-    @Remote
-    public static interface GreenThree {
+    public static interface PurpleBoth {
     }
 
-    public static interface GreenFour {
+    public static interface PurpleUnspecified {
     }
 
-    @Local({GreenOne.class, GreenThree.class})
-    public static class GreenBean implements GreenOne, GreenTwo, GreenThree, 
GreenFour {
+    @Local({PurpleBoth.class})
+    @Remote({PurpleBoth.class})
+    public static class PurpleBean implements PurpleLocal, PurpleRemote, 
PurpleBoth, PurpleUnspecified {
     }
 
     // WhiteBean 
----------------------------------------------------------------
 
-    public static interface WhiteOne {
+    // Not annotated -- xml only
+
+    public static interface WhiteLocal {
+    }
+
+    public static interface WhiteRemote {
+    }
+
+    public static interface WhiteBoth {
+    }
+
+    public static interface WhiteUnspecified {
+    }
+
+    public static class WhiteBean implements WhiteLocal, WhiteRemote, 
WhiteBoth, WhiteUnspecified {
+    }
+
+    // LightOrangeBean 
----------------------------------------------------------------
+
+    // local == xml
+    // remote == annotations on interfaces
+
+    public static interface LightOrangeLocal {
     }
 
     @Remote
-    public static interface WhiteTwo {
+    public static interface LightOrangeRemote {
     }
 
     @Remote
-    public static interface WhiteThree {
+    public static interface LightOrangeBoth {
     }
 
-    public static interface WhiteFour {
+    public static interface LightOrangeUnspecified {
     }
 
-    // local interfaces declared in deployment descriptor
-    //@Local({WhiteOne.class, WhiteThree.class})
-    public static class WhiteBean implements WhiteOne, WhiteTwo, WhiteThree, 
WhiteFour {
+    public static class LightOrangeBean implements LightOrangeLocal, 
LightOrangeRemote, LightOrangeBoth, LightOrangeUnspecified {
     }
 
-    // BlackBean 
----------------------------------------------------------------
+    // LightBlueBean 
----------------------------------------------------------------
+
+    // local == annotations on interfaces
+    // remote == xml
 
     @Local
-    public static interface BlackOne {
+    public static interface LightBlueLocal {
     }
 
-    public static interface BlackTwo {
+    public static interface LightBlueRemote {
     }
 
     @Local
-    public static interface BlackThree {
+    public static interface LightBlueBoth {
+    }
+
+    public static interface LightBlueUnspecified {
+    }
+
+    public static class LightBlueBean implements LightBlueLocal, 
LightBlueRemote, LightBlueBoth, LightBlueUnspecified {
     }
 
-    public static interface BlackFour {
+    // LightRedBean 
----------------------------------------------------------------
+
+    // local == xml
+    // remote == annotations on bean class
+
+    public static interface LightRedLocal {
+    }
+
+    public static interface LightRedRemote {
+    }
+
+    public static interface LightRedBoth {
+    }
+
+    public static interface LightRedUnspecified {
     }
 
-    // remote interfaces declared in deployment descriptor
-    //@Remote({BlackTwo.class, BlackThree.class})
-    public static class BlackBean implements BlackOne, BlackTwo, BlackThree, 
BlackFour {
+    @Remote({LightRedRemote.class, LightRedBoth.class})
+    public static class LightRedBean implements LightRedLocal, LightRedRemote, 
LightRedBoth, LightRedUnspecified {
+    }
+
+    // LightGreenBean 
----------------------------------------------------------------
+
+    // local == annotations on bean class
+    // remote == xml
+
+    public static interface LightGreenLocal {
+    }
+
+    public static interface LightGreenRemote {
+    }
+
+    public static interface LightGreenBoth {
+    }
+
+    public static interface LightGreenUnspecified {
+    }
+
+    @Local({LightGreenLocal.class, LightGreenBoth.class})
+    public static class LightGreenBean implements LightGreenLocal, 
LightGreenRemote, LightGreenBoth, LightGreenUnspecified {
     }
 
 
     // MagentaBean 
----------------------------------------------------------------
 
 
-    public static interface MagentaOne { }
-    public static interface MagentaTwo { }
+    public static interface MagentaLocal {
+    }
+
+    public static interface MagentaRemote {
+    }
 
     @Local
-    @Remote(MagentaTwo.class)
-    public static class MagentaBean implements MagentaOne {
+    @Remote(MagentaRemote.class)
+    public static class MagentaBean implements MagentaLocal {
     }
 
     // CyanBean 
----------------------------------------------------------------
 
-    public static interface CyanOne { }
-    public static interface CyanTwo { }
+    public static interface CyanLocal {
+    }
+
+    public static interface CyanRemote {
+    }
 
-    @Local(CyanOne.class)
+    @Local(CyanLocal.class)
     @Remote
-    public static class CyanBean implements CyanTwo {
+    public static class CyanBean implements CyanRemote {
     }
 
     // PurpleBean 
----------------------------------------------------------------
 
-    public static interface Purple { }
+    public static interface Violet {
+    }
 
     @Local
     @Remote
-    public static class PurpleBean implements Purple {
+    public static class VioletBean implements Violet {
     }
 
 }
\ No newline at end of file


Reply via email to