Topic
5 replies Latest Post - ‏2011-07-14T19:42:54Z by JenniferThompson
SystemAdmin
SystemAdmin
126 Posts
ACCEPTED ANSWER

Pinned topic Obtaining WebService SCA Reference with CompositeContext (or similar way)

‏2011-07-04T15:39:23Z |
Good morning.

I would like to ask a question about obtaining references to SCA Services.

Let me explain our scenario.

I have a SCA component (WSDL Interface, Java implementation) in which I declare a reference to another Service with WebService binding through the @Reference annotation. The component of this second Service has also WebService (only) binding.

Inside the implementation of my first component I have calls to other classes and methods. Inside of them I need to call the reference of the second Service.

I tried to access the service reference with the following line of code:

LoggingPortType service = context.getService(LoggingPortType.class, 
"LoggingComponent/LoggingPortType");

But reading some documentation and redbooks, I discovered that this code only works for components with SCA binding.

My question is: is there any other way to obtain a reference of a Service, with Webservice (only) binding in a similar fashion of the code above?
Updated on 2011-07-14T19:42:54Z at 2011-07-14T19:42:54Z by JenniferThompson
  • SystemAdmin
    SystemAdmin
    126 Posts
    ACCEPTED ANSWER

    Re: Obtaining WebService SCA Reference with CompositeContext (or similar way)

    ‏2011-07-04T17:09:57Z  in response to SystemAdmin
    Hello Alex.

    As far as the SCA domain concerns, there is no way to access this WS service using SCA. You can do so by adding a WS binding to the reference, this way the reference can access a resource outside of the SCA domain.

    I wonder if you can add a SCA binding to the service, this way will be a lot easier to access it from the Context API. Also, one of the greatest benefits of SCA, and SOA in general, is to offer your services in a variety of ways so different people with different programming skills can access to that resource with a minimum effort. Here is an example of how that will be:

    
    <component name=
    "YourComponentWithReference"> <implementation.java class=
    "your.class.Implementation"/> <reference name=
    "yourReference"> <interface.java interface=
    "your.java.Interface"/> <binding.sca/> </reference> </component>   <component name=
    "YourComponentWithService"> <implementation.java class=
    "your.class.Implementation"/> <service name=
    "YourService"> <interface.java interface=
    "your.java.Interface"/> <binding.ws name=
    "yourWSDLBinding" wsdlElement=
    "http://your.wsdl.resolver.uri"/> <binding.sca name=
    "yourSCABinding" /> </reference> </component>
    


    See that the second component is offering the same service in two ways. Now, in your Java reference (first component) you can consume that service thru the context.getService() API (and therefore taking advantage of the SCA benfits), and also you are offering it to the outside world as a Web Service.

    "Software development has been, is, and will remain fundamentally hard"
    - Grady Booch
    • SystemAdmin
      SystemAdmin
      126 Posts
      ACCEPTED ANSWER

      Re: Obtaining WebService SCA Reference with CompositeContext (or similar way)

      ‏2011-07-05T18:16:38Z  in response to SystemAdmin
      Alex,

      Let me expand on Victor's response a bit, since there are a couple different ways to interpret your question. I'm guessing Victor already answered your true question, but just in case not, I'll answer a second question that you could have been asking.

      There is actually a way to programatically access a reference of a component from its implementation.
      This involves the "ComponentContext" API, and it works regardless of binding.

      This isn't hugely useful, however, as the reference injection into the client component implementation proxies is most often easy enough to use without this extra ability.

      But, assuming your client component has a reference, say, loggerRef to your second component's service, LoggingComponent/LoggingPortType, you can do:

      
      
      
      import org.osoa.sca.ComponentContext; 
      
      import org.osoa.sca.annotations.Context;   
      // ...   @Context 
      
      public ComponentContext componentContext;   
      // ...   LoggingPortType service = componentContext.getService(LoggingPortType.class, 
      "loggerRef");
      


      Note the 2nd getService parameter here is the name of the reference in your client component, and doesn't include a reference to your LoggingComponent (the link to this is established through your reference binding value, e.g. the binding "target" value).



      On the other hand, if you were asking how you could get a proxy to the "LoggingComponent/LoggingPortType" without a reference, then I'd refer you to Victor's answer.

      This case involves the WebSphere extension APIs:

      com.ibm.websphere.sca.context.CurrentCompositeContext;
      com.ibm.websphere.sca.context.CompositeContext;

      A nice feature of this API is that you can call it from another SCA component as well as a non-SCA component like a servlet/JSP. However a drawback, as Victor says, is that it only provides access to a service exposed over the default (SCA) binding.
      • SystemAdmin
        SystemAdmin
        126 Posts
        ACCEPTED ANSWER

        Re: Obtaining WebService SCA Reference with CompositeContext (or similar way)

        ‏2011-07-05T18:20:51Z  in response to SystemAdmin
        I was just reading over this after posting and want to clarify:

        When I said,
        Note the 2nd getService parameter ... doesn't include a reference to your LoggingComponent

        I meant to say something like:

        Note the 2nd getService parameter ... doesn't directly refer to the name of your target component/service

        Unfortunately I overloaded the word reference. You are naming the reference, and the reference has to be configured/bound to the target component... I just meant that the actual String passed in as the second parameter value is NOT the name of the target component service.

        Sorry for the confusion.
        • SystemAdmin
          SystemAdmin
          126 Posts
          ACCEPTED ANSWER

          Re: Obtaining WebService SCA Reference with CompositeContext (or similar way)

          ‏2011-07-12T14:20:31Z  in response to SystemAdmin
          Thanks both VictorSosa and ScottKurz.

          Both answers were useful for me.

          I followed ScottKurz's approach because I had already tried VictorSosa's solution. I had some progress following ScottKurz's approach, but I have another question.

          Is it possible to obtain the ComponentContext instance in any different way other than @Context annotation?

          What I'm trying to do now is to call a WebService (Java Implementation, WebService binding), declared in the Component Class, but used by another object. This other object is instanciated by Spring. I cannot use such things as Singletons as they had some considerations in deployment time for the project I want to try this.

          For example:
          
          @Service(MyWebService.class) 
          
          public 
          
          class MyWebServiceImpl 
          
          implements MyWebService 
          {   @Reference 
          
          public LoggingPortType portType;   
          
          public 
          
          void MyWebMethod()
          {   InjectedObject object = 
          // instance an object through Spring ;   object.doSomeLogic();   
          } 
          }
          


          
          
          
          public 
          
          class InjectedObjectImpl 
          
          extends InjectedObject 
          { 
          
          public 
          
          void doSomeLogic()
          {   
          // do something   
          // call here to LoggingPortType reference declared in MyWebServiceImpl class. 
          // do other something 
          }   
          }
          
          • JenniferThompson
            JenniferThompson
            5 Posts
            ACCEPTED ANSWER

            Re: Obtaining WebService SCA Reference with CompositeContext (or similar way)

            ‏2011-07-14T19:42:54Z  in response to SystemAdmin
            Alex,

            To answer your question "Is it possible to obtain the ComponentContext instance in any different way other than @Context annotation?" - the short answer is no. However there are some alternatives to achieve your goal without having to obtain the ComponentContext.

            Since you're obtaining a reference to portType, I'm assuming you've exposed this as a service somewhere in the SCA Domain.

            1) Create a component for for your spring application. For InjectedObjectImpl, define it as an implementation.spring component and expose the spring object as a service. This would allow you to obtain the service reference to portType.
            For example, in your composite file:

            
            <component name=
            "InjectedObjectComponent"> <implementation.spring location=
            "META-INF/injected-context.xml"/> <service name=
            "InjectedObjectService"> <interface.java interface=
            "InjectedObject"/> </service> <reference name=
            "portTypeReference" target=
            "PortTypeComponent/PortTypeService"> <interface.java interface=
            "LoggingPortType"/> </reference> </component>
            


            and your application context "injected-context.xml" would look similar to the following - note that the service and reference names defined in the application context align with what's defined in the composite file. @Reference is not used in the bean definition of InjectedObjectImpl:
            
            <beans xmlns=
            "http://www.springframework.org/schema/beans" xmlns:xsi=
            "http://www.w3.org/2001/XMLSchema-instance" xmlns:sca=
            "http://www.springframework.org/schema/sca" xsi:schemaLocation=
            "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd">   <bean id=
            "InjectedObject" class=
            "InjectedObjectImpl"> <property name=
            "portTypeReference" ref=
            "portTypeReference"/> </bean>   <sca:service name=
            "InjectedObjectService" type=
            "InjectedObject" target=
            "InjectedObject"/> <sca:reference name=
            "portTypeReference" type=
            "LoggingPortType"/>   </beans>
            

            Then in your component for MyWebService create a reference to InjectedObjectService, for example:
            
            <component name=
            "WebServiceComponent"> <implementation.java class=
            "MyWebServiceImpl"/> <service name=
            "MyWebService"> <interface.java interface=
            "MyWebService"/> </service> <reference name=
            "injectedObjectRef" target=
            "InjectedObjectComponent/InjectedObjectService"> <interface.java interface=
            "InjectedObject"/> </reference> </component>
            


            Then in MyWebServiceImpl you access the service implemented by spring in by using the @Reference annotation to obtain the reference implemented by spring:
            
            @Reference 
            
            protected InjectedObject injectedObjectRef;
            

            There are a few drawbacks to this to this approach including

            a) implementation.spring support is limited, including not having access to an application namespace, not supporting SCA annotations and not supporting PassByReference. Refer to these two InfoCenter articles for more information:

            http://www14.software.ibm.com/webapp/wsbroker/redirect?version=v701sca&product=was-nd-mp&topic=tsca_spring_impl
            http://www14.software.ibm.com/webapp/wsbroker/redirect?version=v701sca&product=was-nd-mp&topic=csca_spec_gaps

            b) Since PassByReference is not supported, this may cause a lot of overhead for copying data values. If you try this path, you should put annotate your interface with @Remoteable.

            2) Although support for implementation.spring is limited, our support for implementations leveraging applications using "WebSphere Application Server V7 Feature Pack for OSGi Applications" have significantly more capability. You could consider porting your spring application to an OSGi application, and then define two components as outlined above (except obviously changing the component implementation and creating a blueprint to expose the equivalent services and obtain equivalent references). The following article describes migrating a spring application to an OSGi application:

            http://www.ibm.com/developerworks/websphere/techjournal/1103_mahrwald/1103_mahrwald.html?ca=drs-

            And this SCA Information Center article describes creating an implementation.osgiapp component:

            http://www14.software.ibm.com/webapp/wsbroker/redirect?version=v701sca&product=was-nd-mp&topic=tsca_osgi_impl