11 Replies Latest reply on Mar 30, 2015 10:22 AM by morols

    How to use sca binding to call from one application to a service in another application

    morols

      Hi,

       

      I have two applications deployed as JARs in a standalone JBoss instance. I want to make a call from inside one application to a bean in the other application.

       

      In the switchyard.xml of the application that has the implementation, I have the following:

      ...
      <sca:composite name="magicktrader" targetNamespace="urn:magicktrader:0.1.0">
          ...
          <sca:service name="MarketDataService" promote="MarketDataBean/MarketDataService">
            <sca:interface.java interface="nu.magick.masterKonnector.service.MarketDataService"/>
            <sca:binding.sca/>
          </sca:service>
          <sca:component name="MarketDataBean">
            <bean:implementation.bean class="com.magick.magicktrader.MarketDataServiceBean"/>
            <sca:service name="MarketDataService">
              <sca:interface.java interface="nu.magick.masterKonnector.service.MarketDataService"/>
            </sca:service>
          </sca:component>
      

       

      In the switchyard.xml of the application that wants to make the call, I have:

      ...
        <sca:composite name="BackTestKonnector" targetNamespace="ck:BackTestKonnector:0.0.1-SNAPSHOT">
          ...
          <sca:reference name="MarketDataService" multiplicity="0..1" promote="BackTestTickListener/MarketDataService">
            <sca:interface.java interface="nu.magick.masterKonnector.service.MarketDataService"/>
            <sca:binding.sca sy:clustered="false" sy:target="MarketDataService" sy:targetNamespace="urn:magicktrader:0.1.0"/>
          </sca:reference>
          <sca:component name="BackTestTickListener">
            <bean:implementation.bean class="nu.magick.backTestKonnector.service.listener.BackTestTickListener"/>
            <sca:reference name="MarketDataService">
              <sca:interface.java interface="nu.magick.masterKonnector.service.MarketDataService"/>
            </sca:reference>
          </sca:component>
      

       

      Finally, inside the class that wants to use the service, I have the following:

       

      @Inject
      @Reference
      private MarketDataService marketDataService;
      

       

      But when I try to use the marketDataService it is null. Any help will be appreciated.

       

      Thanks,

      Morten

        • 1. Re: How to use sca binding to call from one application to a service in another application
          kcbabo

          Are you importing javax.inject.Inject or another flavor of Inject (e.g. com.google.inject)?

          • 2. Re: How to use sca binding to call from one application to a service in another application
            jorgemoralespou_2

            Hi Morten,

            There can be many problems here, although, some error should be shown.

            If it is null, the most probable answer is the one Keith provided, wrong Inject (we've seen this before).

            Also, you can have more than one reference to a MarketDataService on the same composite, in which case, you'll need to disambiguate it through the appropriate name of the appropriate MarketDataService reference. Just think that it searches for a reference of the type MarketDataService and not with the name MarketDataService.

             

            But, this should be very easy to solve, as it should be only one of those two possible options, when the injected point is null.

             

            Also, you need to be sure that you don't have any strange CDI scope in your service, like @Singleton and @Startup, which will make it initialize before the classes that are being injected, and thus, you'll get a null. But this is a very strange usecase.

             

            Hope you solve it soon.

            1 of 1 people found this helpful
            • 3. Re: How to use sca binding to call from one application to a service in another application
              morols

              Yes, I have this "import javax.inject.Inject;" for the injection.

              • 4. Re: How to use sca binding to call from one application to a service in another application
                kcbabo

                Best to package up your app or a sample that demonstrates this behavior and attach to the thread.  If the reference is null, injection is not happening, which points to CDI.  Is there a beans.xml in your packaged app?

                1 of 1 people found this helpful
                • 5. Re: How to use sca binding to call from one application to a service in another application
                  morols

                  Thanks for the help guys.

                   

                  1) It does not appear to be the injection.

                   

                  2) Regarding having multiple services, I'm not sure I fully understand.

                  In the application that is to make the call there is no mentioning of services by the same name/type (except the one I have just added to try to make the call).

                  In the application that has the implementation I'm hoping to invoke, there are some services exposed for JMS, like below, with the same interface and names like MarketDataService1, -2 and -3.

                   

                          <sca:service name="MarketDataService1" promote="MarketDataService/MarketDataService">

                              <sca:interface.java interface="nu.magick.masterKonnector.service.MarketDataService"/>

                              <jms:binding.jms>

                                  <operationSelector operationName="getData"/>

                                  <jms:topic>marketDataTopic1</jms:topic>

                                  <jms:connectionFactory>#ConnectionFactory</jms:connectionFactory>

                              </jms:binding.jms>

                          </sca:service>

                   

                  I'm not sure, how I would go about disambiguating the service name/type - what to change?

                   

                  3) I've searched the two projects for use of @Singleton and @Startup and found:

                  In the project I'm trying to invoke the bean in, there are no @Startup annotations. There is @Singleton annotations on three classes. None of these have references to the MarketDataServices.

                  In the project I'm trying to call from, there are also no @Startup annotations. There is @Singleton annotations on four classes. None of these have references to the MarketDataServices.

                  Is this problematic?

                   

                  The applications are currently communicating through JMS. I'm trying to get the application to make a direct call to the other application now to see the performance difference (as performance measurements showed around 30% spend in JMS for some scenario where the two applications coexist on the same server anyway).

                   

                  Bests,

                  Morten

                  • 6. Re: How to use sca binding to call from one application to a service in another application
                    morols

                    The two applications are deployed as JARs in the deployment directory of JBoss, while the shared interface is located in a module. All of the JARs have a beans.xml in their META-INF directory. Two of them do not contain anything but the XML and beans elements, while the beans.xml for the application with the implementation also has this interceptor part:

                    <?xml version="1.0"?>

                    <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                          xsi:schemaLocation="    http://java.sun.com/xml/ns/javaee      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

                        <interceptors>

                            <class>com.magick.magicktrader.trade.interceptor.BackTestInterceptor</class>

                        </interceptors>

                    </beans>

                     

                    Thanks for the help so far. I will look into packaging up/extracting an example, and see if I'm able.

                    • 7. Re: How to use sca binding to call from one application to a service in another application
                      morols

                      I've created a new simple project with what I'm trying to do, and after some attempts it seems to work. The example unfortunately do not have use of the same service or singleton annotations, but maybe I can try to make it look more like my real applications or cut out parts of the real applications to get here. I'll return if I find the real issue or get stuck again

                       

                      I appreciate the help,

                      Morten

                      • 8. Re: How to use sca binding to call from one application to a service in another application
                        morols

                        Hi again,

                         

                        After creating the simple example that worked, I'm now trying to strip away stuff from my real application to get a smaller example which I might be able to share. Unfortunately the application with the service to get called, have a lot of services and it might take me a long while to determine what I can strip away.

                         

                        Is there any way I can verify what parts are working?

                        If I look in the management console, it seems the service and the reference is up and running. Will that narrow the issue down to one of the applications? Will it narrow it down to a certain area, e.g. the @Singleton annotations?

                         

                        Bests,

                        Morten

                        • 9. Re: How to use sca binding to call from one application to a service in another application
                          jorgemoralespou_2

                          Morten,

                          some options:

                          For you case, as the callee seems never get called, just create a test service (mock SCA service), and replace the reference to call this test service, or replace the service with this mock service (as you prefer). Everything in the callee should be able to be stripped, as your problem is not getting the reference properly injected.

                           

                          Other options:

                          - Enable more logging on startup. I've seen sometimes CDI errors not being printed as default level hided these errors. So start adding different categories for org.switchyard, and cdi resolution (don't remember appropriate categories)

                          - Check that the service is properly started. You can do it with JMX looking at the service binding and getState().

                          - Create a RemoteInvoker client that invokes your target service via SCA to see if it works.

                          - If it works, then the problem is on the reference side, so the caller, not the callee.

                          - Try to strip unneded features (like singletons, and simplify your path of execution, everything else, that it is not in the path of execution, remove it)

                           

                          And finally:

                          - Verify that every application has it's own namespace (THIS IS VERY IMPORTANT!!!)

                           

                          Of course, without access to the source code, it is difficult to help, but you should be able to narrow down the problem with this tips.

                           

                          Hope it helps, and of course, if it is FSW you are using, open a support case @ Red Hat.

                           

                          By the way, which version of SY are you using?

                          1 of 1 people found this helpful
                          • 10. Re: How to use sca binding to call from one application to a service in another application
                            morols

                            I've managed to strip the actual applications down to example level (see attachment). In the example I have two applications (I've called "caller" and "callee"). They both have REST services to get started. To look somewhat similar to our real applications' scenario, the flow is as follows:

                            1. The "callee" is first started by manually making a GET request to it's start service (http://localhost:xxxx/callee/start).
                            2. The "callee" will then start the "caller" by making a REST call to it (I've hard coded the URL in the StartServiceBean of "callee", which may need to be changed if one is using a different port than 8079).
                            3. Once started the "caller" will try to call the service in the callee through the sca binding.

                             

                            The call made by the "caller" is made somewhat indirectly; the StartServiceBean uses a RunnerServiceBean to perform the actual call. What I've found is that:

                            • When I instantiate new RunnerServiceBean instances inside the StartServiceBean, the RunnerServiceBean instances do not get a reference to the sca-service in the other application.
                            • When I wire the RunnerService into the StartService (so there is only one instance) it works.

                             

                            I will try on Monday to utilise this information and see if I can wire the service where I need it for the communication - alternatively wire it on something like the StartServiceBean and then pass it around until needed for the call (in my real world scenario it is not the Runner instance itself that need to do the communication with the other application).

                             

                            Thanks for the help so far,

                            Morten

                            • 11. Re: How to use sca binding to call from one application to a service in another application
                              morols

                              Thanks for the help guys and pushing me towards stripping away everything so I could see the difference between the simple example I made and the applications.

                               

                              The issue seemed to be that I was trying to get the service from the other application injected into an object that was instantiated "manually". I rewrote, so the service now gets injected into the object that performs the manual instantiation and now it just passes the reference to the service on to the newly created instance instead.

                               

                              Bests,

                              Morten