Pages

Sunday, December 13, 2009

SCA Spring in Weblogic 10.3.2 & Soa Suite 11g

With Weblogic 10.3.2 ( part of Patch Set 1 of Fusion Middleware R1 ) Oracle released a preview of SCA Spring. For more info about this announcement see the blog of Raghav.
This is great news because everything what works in SCA Spring can be used without any problem in Soa Suite 11g. With Patch Set 2 SCA Spring will be supported in WLS or Soa Suite. For a Soa Suite Spring example see this blog of Clemens

To test this I made a small example based on the blog of Clemens. In this test I will call a logging webservice and this service will pass the call to a passthrough bean which has a reference to an logging EJB service which calls a logging bean and this bean has an other bean injected which does the output.

First deploy the weblogic-sca war as a library to the WLS server, you can find this war in wlserver_10.3/common/deployable-libraries/ folder and is called weblogic-sca-1.0.war

Create in JDeveloper a new web project ( no need for ADF ) . We don't need the spring jar or add some config in the web.xml ( this can be empty , don't need to add spring listener )

Add a library reference in your webapp to the weblogic-sca library, Do this in the weblogic.xml or weblogic-application.xml file
<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
                 xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
   <library-ref>
       <library-name>weblogic-sca</library-name>
   </library-ref>
</weblogic-web-app>

Create a spring from jdeveloper and call this file spring-context.xml and put this in META-INF/jsca folder ( in the src folder )
When you got experience with Apache Tuscany then this spring configuration is not so difficult.
<?xml version="1.0" encoding="windows-1252" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca"
      xmlns:wlsb="http://xmlns.oracle.com/weblogic/weblogic-sca-binding"
      xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://xmlns.oracle.com/weblogic/weblogic-sca http://xmlns.oracle.com/weblogic/weblogic-sca/1.0/weblogic-sca.xsd http://xmlns.oracle.com/weblogic/weblogic-sca-binding http://xmlns.oracle.com/weblogic/weblogic-sca-binding/1.0/weblogic-sca-binding.xsd">
 <!--Spring 2.5 Bean defintions go here-->
 <sca:service target="loggerPassThrough" name="LogServiceWS"
              type="nl.whitehorses.wls.sca.spring.ILoggerComponent">
   <wlsb:binding.ws xmlns="http://xmlns.oracle.com/sca/1.0"
               name="LoggerService_WS" uri="/LoggerService_Uri"
               port="LoggerService_PORT"/>
 </sca:service>

 <sca:reference name="loggerEJBReference"
 type="nl.whitehorses.wls.sca.spring.ILoggerComponent">
   <wlsb:binding.ejb uri="LoggerService_EJB30_JNDI" />
 </sca:reference>

 <bean class="nl.whitehorses.wls.sca.spring.LoggerPassThrough" name="loggerPassThrough">
    <property name="reference" ref="loggerEJBReference" />
 </bean>

 <sca:service target="logger" name="LogServiceEJB"
              type="nl.whitehorses.wls.sca.spring.ILoggerComponent">
   <wlsb:binding.ejb uri="LoggerService_EJB30_JNDI" remote="true"
                     name="LoggerService_EJB"/>
 </sca:service>

 <bean class="nl.whitehorses.wls.sca.spring.LoggerComponentImpl" name="logger">
    <property name="output" ref="loggerOutput" />
 </bean>

 <bean id="loggerOutput" class="nl.whitehorses.wls.sca.spring.LoggerOutput"></bean>

</beans>

Now we need to create a logger interface, this will be use by the WS & EJB services and references.
package nl.whitehorses.wls.sca.spring;

public interface ILoggerComponent
{
   
    /**
     * Log a message, including the originating component, its instance id and
     * a message.
     * @param pComponentName the name of the component that sends this log msg
     * @param pInstanceId the instanceId of the component instance
     * @param pMessage the message to be logged
     */
    public void log (String pComponentName,
                     String pInstanceId, String pMessage);
}

Create a passthrough class this will pass on the logger call to the ejb service.
package nl.whitehorses.wls.sca.spring;

public class LoggerPassThrough implements ILoggerComponent {
    public LoggerPassThrough() {
        super();
    }

    @Override
    public void log(String pComponentName, String pInstanceId,
                    String pMessage)  {
    
       reference.log(pComponentName, pInstanceId, pMessage);
    }

    private ILoggerComponent reference;

    public void setReference(ILoggerComponent reference) {
        this.reference = reference;
    }

    public ILoggerComponent getReference() {
        return reference;
    }

}

Create the logger implementation class.
package nl.whitehorses.wls.sca.spring;

public class LoggerComponentImpl implements ILoggerComponent {
    public LoggerComponentImpl() {
        super();
    }

    @Override
    public void log(String pComponentName, String pInstanceId,
                    String pMessage)  {
       output.logToConsole(pComponentName, pInstanceId, pMessage);
    }

    private LoggerOutput output;

    public void setOutput(LoggerOutput output) {
        this.output = output;
    }

    public LoggerOutput getOutput() {
        return output;
    }
}

The last class prints the console output
package nl.whitehorses.wls.sca.spring;

public class LoggerOutput {
    public LoggerOutput() {
        super();
    }
    
    public void logToConsole(String pComponentName, String pInstanceId,  String pMessage)
    {
        StringBuffer logBuffer = new StringBuffer ();
        logBuffer.append("[").append(pComponentName).append("] [Instance: ").
            append(pInstanceId).append("] ").append(pMessage);
        
        System.out.println(logBuffer.toString());
    }
}


Deploy the web application the weblogic server and use soapui to test the service. The wsdl url is in my case http://laptopedwin.wh.lan:7001/WlsSpring-ScaSpring-context-root/LoggerService_Uri?WSDL or make a EJB test client and use this ILoggerComponent logger = (ILoggerComponent)context.lookup("LoggerService_EJB30_JNDI");

Here you can download my code on github https://github.com/biemond/jdev11g_examples/tree/master/WlsSpring

13 comments:

  1. hi,

    your example workspace file is corrupt, it cannot be unzipped

    ReplyDelete
  2. hi,
    why my jdeveloper 11.1.1.2.0 cannot open composite.xml includes sca componenty, it will show a error of "failed to locate the component type in configuration file"


    thanks
    Patrick

    ReplyDelete
  3. Hi,

    thanks I will take a look at the zip,
    did you enable spring in jdev 11g ps1

    In order to use this preview feature in SOA Suite 11g PS1, you must first enable preview mode. Go to $JDeveloper_HOME/integration/seed/soa/configuration and open soa-config.xml. Search for ${SPRING_COMPONENT_NAME_L} and remove the xml comments () around it. After you've saved the file, restart JDeveloper

    thanks

    ReplyDelete
  4. Hi,
    after uncomment components in Jdeveloper I can open the file;
    and
    I can unzipped downloadable file in IE but got error in FirxFox, it's strange.

    thanks

    ReplyDelete
  5. Hi,
    Just downloaded your zip file and the war inside the dist folder was not being able to activate with the following exception:


    User defined listener weblogic.jscalite.container.WebLogicJScaLiteContextListener failed: java.lang.NoClassDefFoundError: org/springframework/beans/BeansException.
    java.lang.NoClassDefFoundError: org/springframework/beans/BeansException
    at weblogic.jscalite.engine.WebLogicJScaLiteImplementation.loadComponentModel(WebLogicJScaLiteImplementation.java:41)
    at weblogic.jscalite.container.WebLogicJScaLiteDeploymentManager.deploy(WebLogicJScaLiteDeploymentManager.java:43)
    at weblogic.jscalite.container.WebLogicJScaLiteContextListener.deploy(WebLogicJScaLiteContextListener.java:79)
    at weblogic.jscalite.container.WebLogicJScaLiteContextListener.contextInitialized(WebLogicJScaLiteContextListener.java:32)
    at weblogic.servlet.internal.EventsManager$FireContextListenerAction.run(EventsManager.java:481)


    Which I was able to fix by including the spring.jar file inside ScaSpring.ear/webapp.war/WEB-INF/lib.
    Anyway, a good article and will refer to it in my currently article about JSCA + Weblogic.

    Regards

    ReplyDelete
  6. Ok Thanks,

    Did you do this.

    First deploy the weblogic-sca war as a library to the WLS server, you can find this war in wlserver_10.3/common/deployable-libraries/ folder and is called weblogic-sca-1.0.war

    Add a library reference in your webapp to the weblogic-sca library, Do this in the weblogic.xml or weblogic-application.xml file

    thanks and let me know the url of your article.

    ReplyDelete
  7. Have you come across a way to change default transaction propagation when you expose your component as an EJB?

    ReplyDelete
  8. Hi Alex,

    I can't find anything about this subject in the wls sca spring documentation.

    What is the reason you need to change this or waht is the use case.

    thanks

    ReplyDelete
  9. Hi,
    Thanks for the great example, just wondering if you have tried to implement Async request/response interaction using callback, I could not seem to find any documentation on how to do this in Weblogic SCA.

    Thanks in advance
    Brian

    ReplyDelete
  10. Hi,

    I think I read somewhere that Async is not supported. You need then some correlation and some tech to handle long async requests.

    thanks

    ReplyDelete
  11. Hi Edwin,

    In your example you have placed only one method in ILoggerComponen Interface. Can we place more than one method in this Interface, if so then how can we tell the Spring Context Which method is being called.

    ReplyDelete
    Replies
    1. Hi,

      interesting question, I don't know maybe it is just like bpel and mediatior with only one wsdl ( off course here you can have more than 1 operation ) . I only see 1 sca:service in the bean spring but you can try it out ,maybe you will get a choice to select the method when you wire a connection from a mediator to this spring component.

      Thanks

      Delete