diff options
author | antelder <antelder@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-15 12:52:34 +0000 |
---|---|---|
committer | antelder <antelder@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-15 12:52:34 +0000 |
commit | 3d1dac50bc546b01493af516ce2d2f5f2d6d9e04 (patch) | |
tree | 897e4ed3bf86631580230bace29beb2563b77e00 | |
parent | b0ce588bf60f88bceb796701a883a02392beb0aa (diff) |
TUSCANY-3300, Update @Service annotation to match the latest SCA-J CAA spec
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@825483 13f79535-47bb-0310-9956-ffa450edef68
6 files changed, 102 insertions, 38 deletions
diff --git a/java/sca/modules/binding-sca-axis2-runtime/src/test/java/org/apache/tuscany/sca/binding/sca/axis2/helloworld/impl/HelloWorldServiceMultipleServicesImpl.java b/java/sca/modules/binding-sca-axis2-runtime/src/test/java/org/apache/tuscany/sca/binding/sca/axis2/helloworld/impl/HelloWorldServiceMultipleServicesImpl.java index be516123c3..846bff02e1 100644 --- a/java/sca/modules/binding-sca-axis2-runtime/src/test/java/org/apache/tuscany/sca/binding/sca/axis2/helloworld/impl/HelloWorldServiceMultipleServicesImpl.java +++ b/java/sca/modules/binding-sca-axis2-runtime/src/test/java/org/apache/tuscany/sca/binding/sca/axis2/helloworld/impl/HelloWorldServiceMultipleServicesImpl.java @@ -24,7 +24,7 @@ import org.apache.tuscany.sca.binding.sca.axis2.helloworld.HelloWorldServiceRemo import org.apache.tuscany.sca.binding.sca.axis2.helloworld.HelloWorldServiceRemote2; import org.oasisopen.sca.annotation.Service; -@Service(interfaces={HelloWorldServiceRemote.class, HelloWorldServiceRemote2.class, HelloWorldServiceLocal.class} ) +@Service({HelloWorldServiceRemote.class, HelloWorldServiceRemote2.class, HelloWorldServiceLocal.class} ) public class HelloWorldServiceMultipleServicesImpl implements HelloWorldServiceLocal, HelloWorldServiceRemote, HelloWorldServiceRemote2 { public String getGreetingsLocal(String s) { diff --git a/java/sca/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java b/java/sca/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java index 71a711261f..ec7507f97e 100644 --- a/java/sca/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java +++ b/java/sca/modules/implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java @@ -25,6 +25,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.Set; import java.util.logging.Logger; @@ -83,20 +85,28 @@ public class ServiceProcessor extends BaseJavaClassVisitor { } return; } - Class<?>[] interfaces = annotation.interfaces(); - if (interfaces.length == 0) { - Class<?> interfaze = annotation.value(); - if (Void.class.equals(interfaze)) { - //throw new IllegalServiceDefinitionException("No interfaces specified"); - logger.warning("Ignoring @Service annotation. No interfaces specified. class = "+clazz.getName()); - } else { - interfaces = new Class<?>[1]; - interfaces[0] = interfaze; + + if (annotation.value().length == 0) { + throw new IntrospectionException("JCA90059 The array of interfaces or classes specified by the value attribute of the @Service annotation MUST contain at least one element"); + } + Class<?>[] interfaces = annotation.value(); + if (annotation.names().length > 0) { + if (annotation.names().length != interfaces.length) { + throw new IntrospectionException("JCA90050 The number of Strings in the names attribute array of the @Service annotation MUST match the number of elements in the value attribute array"); + } + Set<String> names = new HashSet<String>(); + names.addAll(Arrays.asList(annotation.names())); + if (names.size() != annotation.names().length) { + throw new IntrospectionException("JCA90060 The value of each element in the @Service names array MUST be unique amongst all the other element values in the array"); } } - for (Class<?> interfaze : interfaces) { + + for (int i=0; i < interfaces.length; i++) { try { - Service service = createService(interfaze); + Service service = createService(interfaces[i]); + if (annotation.names().length > 0) { + service.setName(annotation.names()[i]); + } type.getServices().add(service); } catch (InvalidInterfaceException e) { throw new IntrospectionException(e); diff --git a/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java b/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java index a163652ead..6cc8b1777b 100644 --- a/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java +++ b/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java @@ -304,7 +304,6 @@ public class HeuristicPojoProcessorTestCase extends AbstractProcessorTest { void operation1(String param1); } - @Service private interface PropertyNonRemotableInterface { void operation1(String param1); } @@ -568,7 +567,7 @@ public class HeuristicPojoProcessorTestCase extends AbstractProcessorTest { void serviceOperation1(); } - @Service + @Service(SomeWebService.class) private static class SomeWebServiceImpl implements SomeWebService { public SomeWebServiceImpl() { diff --git a/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java b/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java index 1a7889366e..286b0d70d1 100644 --- a/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java +++ b/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java @@ -288,7 +288,7 @@ public class PolicyProcessorTestCase { int method6(); } - @Service(interfaces = {Interface1.class, Interface2.class}) + @Service({Interface1.class, Interface2.class}) private class Service2 implements Interface1, Interface2 { public int method1() { return 0; @@ -353,7 +353,7 @@ public class PolicyProcessorTestCase { int method6(); } - @Service(interfaces = {Interface3.class, Interface4.class}) + @Service({Interface3.class, Interface4.class}) @Requires( {"transaction.local"}) private class Service4 implements Interface3, Interface4 { public int method1() { diff --git a/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java b/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java index 528639a008..14eadfe6a2 100644 --- a/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java +++ b/java/sca/modules/implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java @@ -20,12 +20,14 @@ package org.apache.tuscany.sca.implementation.java.introspect.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import javax.jws.WebService; import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; import org.apache.tuscany.sca.implementation.java.JavaImplementation; import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; @@ -96,12 +98,44 @@ public class ServiceProcessorTestCase { } @Test - public void testNoInterfaces() throws Exception { + public void testMultiplenamedInterfaces() throws Exception { + processor.visitClass(FooMultipleNamed.class, type); + assertEquals(2, type.getServices().size()); + org.apache.tuscany.sca.assembly.Service sbaz = type.getService("BazName"); + assertNotNull(sbaz); + assertEquals(Baz.class, ((JavaInterface)sbaz.getInterfaceContract().getInterface()).getJavaClass()); + org.apache.tuscany.sca.assembly.Service sbar = type.getService("BarName"); + assertNotNull(sbar); + assertEquals(Bar.class, ((JavaInterface)sbar.getInterfaceContract().getInterface()).getJavaClass()); + } + + @Test + public void testBadService() throws Exception { + try { + processor.visitClass(BadService.class, type); + fail(); + } catch (IntrospectionException e) { + assertTrue(e.getMessage().startsWith("JCA90059")); + } + } + + @Test + public void testBadServiceNames() throws Exception { try { - processor.visitClass(BadDefinition.class, type); - } catch (IllegalServiceDefinitionException e) { - //not expected + processor.visitClass(BadServiceNames.class, type); fail(); + } catch (IntrospectionException e) { + assertTrue(e.getMessage().startsWith("JCA90050")); + } + } + + @Test + public void testBadServiceDuplicateNames() throws Exception { + try { + processor.visitClass(BadServiceDuplicateNames.class, type); + fail(); + } catch (IntrospectionException e) { + assertTrue(e.getMessage().startsWith("JCA90060")); } } @@ -130,7 +164,7 @@ public class ServiceProcessorTestCase { private interface BazRemotable { } - @Service(interfaces = {Baz.class, Bar.class}) + @Service({Baz.class, Bar.class}) private class FooMultiple implements Baz, Bar { } @@ -160,10 +194,23 @@ public class ServiceProcessorTestCase { } + @Service(value={Baz.class, Bar.class}, names={"BazName", "BarName"}) + private class FooMultipleNamed implements Baz, Bar { + + } - @Service() - private class BadDefinition extends FooSingle { + @Service(value={}) + private class BadService implements Baz { } + @Service(value={Baz.class, Bar.class}, names={"BazName"}) + private class BadServiceNames implements Baz, Bar { + + } + + @Service(value={Baz.class, Bar.class}, names={"BazName", "BazName"}) + private class BadServiceDuplicateNames implements Baz, Bar { + + } } diff --git a/java/sca/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Service.java b/java/sca/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Service.java index 36c5bff5e9..a60754762e 100644 --- a/java/sca/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Service.java +++ b/java/sca/modules/sca-api/src/main/java/org/oasisopen/sca/annotation/Service.java @@ -1,37 +1,45 @@ /* - * (c) Copyright BEA Systems, Inc., Cape Clear Software, International Business Machines Corp, Interface21, IONA Technologies, - * Oracle, Primeton Technologies, Progress Software, Red Hat, Rogue Wave Software, SAP AG., Siemens AG., Software AG., Sybase - * Inc., TIBCO Software Inc., 2005, 2007. All rights reserved. - * - * see http://www.osoa.org/display/Main/Service+Component+Architecture+Specifications + * Copyright(C) OASIS(R) 2005,2009. All Rights Reserved. + * OASIS trademark, IPR and other policies apply. */ package org.oasisopen.sca.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; - import java.lang.annotation.Retention; import java.lang.annotation.Target; /** - * Annotation used to indicate the service interfaces exposed by a Java class. + * The @Service annotation is used on a component implementation + * class to specify the SCA services offered by the implementation. + * + * The class need not be declared as implementing all of the + * interfaces implied by the services, but all methods of the service + * interfaces must be present. * - * @version $Rev$ $Date$ + * A class used as the implementation of a service is not required + * to have a @Service annotation. If a class has no @Service annotation, + * then the rules determining which services are offered and what + * interfaces those services have are determined by the specific + * implementation type. */ -@Target({TYPE}) +@Target(TYPE) @Retention(RUNTIME) public @interface Service { + /** - * Array of interfaces that should be exposed as services. + * The value is an array of interface or class objects that should be + * exposed as services by this component. * - * @return a list of interfaces that should be exposed as services + * @return the services of this component */ - Class<?>[] interfaces() default {}; + Class<?>[] value(); /** - * Shortcut allowing a single interface to be exposed. + * The value is an array of strings which are used as the service names + * for each of the interfaces declared in the value array. * - * @return a single service interfaces to be exposed + * @return the service names */ - Class<?> value() default Void.class; + String[] names() default {}; } |