Pages

Sunday, August 11, 2013

Coherence 12.1.2 Rest application build with OEPE

With WebLogic 12.1.2 Oracle also released a new version of Coherence and OEPE. The 12.1.2 release contains many new Coherence features like WebLogic Managed Coherence Servers and Coherence Grid Archive ( GAR ) which can be included in an normal EAR. Coherence also has some nice new REST features like direct & named queries,  Custom Query engines and new Security options.
Plus with OEPE you can develop Coherence applications in Eclipse and it has Coherence editors for all the Coherence configuration files.

In this blogpost we will test these tools and features in a demo application which uses the HR Oracle demo schema, JPA and expose these entities as Coherence REST Services.

We start by downloading OEPE Eclipse runtime bundle with WebLogic 12.1.2, Coherence and ADF http://www.oracle.com/technetwork/developer-tools/eclipse/downloads/index.html

Start OEPE and define a new workspace.

Create an Oracle Coherence Application


Provide a project name and make sure you define a target runtime.  Plus enable Add project to EAR.


Use the default Coherence options.


The Coherence application will also add a dynamic Web project.


JPA Project
For this demo I will use JPA so we can use these entities in Coherence.


Also target this to WebLogic 12.1.2 and add this project to the already existing EAR project.


Define an connection to the database this will also add a persistence unit to the JPA project.


Next choose JPA entities from tables, where I select the Departments and Employees tables for this demo


Change the JPA mapping relations between the Department and Employee entities and add for REST the XML annotations.
Like @XmlRootElement(name="Department")  and @XmlTransient on the getters to break the loop of loading the Department and Employee objects.

Coherence Project
Next step is to configure the Coherence.
We can use the OEPE Coherence Editors or go directly to the source tab.


First we change coherence-cache-config.xml file where we will define the Department and Employee cache and connect this to EclipseLink.

HrJPA is the name of the Persistence Unit ( Resource Local )

Create a new file called coherence-rest-config.xml, this contains our REST entity definitions where we add some coherence named queries and enable the direct query option.

<key-class>java.lang.Integer</key-class> must match with the primary Java Data type of the entity


The last file we need to change is the pof-config.xml and add <include>coherence-rest-pof-config.xml</include> to the user-type-list

Also upload the coherence-rest.jar to the lib folder of the CoherenceJPA project.

Web project
Last step is to enable the Web project for Coherence REST. We need to enable the Oracle Coherence Facet on this Web Project.


Remove all the Coherence files located in the src folder, we don't need this.

Add the following Coherence REST Servlet.


Also we need to add the following Jersey and Jackson jars files to the WEB-INF lib folder. ( Located  in the module folder of the oracle_common )



Also create your own servlet, so we can fill the Department and Employee Coherence cache ( else the cache will be empty )



In the Eclipse Servers tab we need to add an WebLogic Domain with a Managed Coherence Server ( maybe use right click to select an WebLogic target other than the default AdminServer.


For we Coherence REST we need to change the default EclipseLink JAXB provider.

Add these parameters to Server startup arguments to the Managed Server
-Dcom.sun.xml.ws.spi.db.BindingContextFactory=com.sun.xml.ws.db.glassfish.JAXBRIContextFactory 
-Djavax.xml.bind.JAXBContext=com.sun.xml.bind.v2.ContextFactory

Publish the EAR from OEPE which also contains the Grid Archive (GAR) to the Coherence Managed Server

Finally we can test the Rest service
Start by invoking the servlet http://wls12:7201/CoherenceJPAWeb/CoherenceServlet

Next we can use a Rest Client to test all the Rest operations.

Get all the department entries
http://wls12:7201/CoherenceJPAWeb/rest/Department



Get Deparment 100
http://wls12:7201/CoherenceJPAWeb/rest/Department/100


Add a new Department
 Delete a department

Direct query ( enabled in the coherence rest config xml )
http://wls12:7201/CoherenceJPAWeb/rest/Department?q=departmentName='Finance'


Location1700 Named query also defined in the coherence rest config xml


Location Named query with a integer parameter


Here you can download or look at the github demo project.

Thursday, August 1, 2013

JAX-WS SOAP over JMS

With WebLogic 12.1.2 Oracle now also supports JAX-WS SOAP over JMS. Before 12.1.2 we had to use JAX-RPC and without any JDeveloper support. We need to use ANT to generate all the web service code. See this blogpost for all the details.

In this blogpost I will show you all the necessary JDeveloper steps to create a SOAP over JMS JAX-WS Web Service  ( Bottom up approach) and generate a Web Service Proxy client to invoke this service, plus let you know what works and what not.

We start with a simple HelloService class with a sayHello method.


After this we can start the Create Java Web Service wizard.


Select our HelloService class


Select our sayHello method


This will generated the following code.  Besides @WebService , @WebMethod and @WebParam annotation we can change the name attribute of the WebParam annotation and optional add the WebResult annotation.


Next step is to add the @JMSTransportService annotations on this HelloService class.
This will import com.oracle.webservices.api.jms.JMSTransportService class.


When we click on this annotation we modify all the JMS transport properties in the JDeveloper property window


We can also change this Web Service activation properties.


With this as result.

I will use localhost as jndiURL, when you change this to the server url ( you can't deploy it to an other server)  but then you can invoke this JMS service by generating a JAX-WS proxy client without changing anything.


Before we can deploy this Web Service to a WebLogic Domain we need to extend this domain with the WebLogic JAX-WS SOAP/JMS Extension ( or add $WebLogicHome/common/templates/wls/wls_webservice_soapjms.jar template with WLST )


This will create the following Queues and Connection Factory in its own JMS module and JMS Server


We can deploy the Web Service to the JAX-WS WebLogic Domain. 


Also retrieve the WSDL with HTTP.


The WSDL show all our JMS properties in the SOAP Binding and as one string in the soap address location attribute.


Next step is generating a JAX-WS Client and invoke this JMS service. 
Select our Web Service,  from there we can generate a new Web Service client.



Do this in a new project called JmsClient


Enable Copy WSDL into Project.


Leave the default url as it is, even when it is not valid.


Next we can change the PortClient class so it won't use HTTP to invoke this service. 


The documentation says we can do this in 3 ways ( for me only one way really works )

We can JMSTransportClient annotation to our Service class

@WebServiceClient(name = "HelloService",
                  targetNamespace = "http://jms.ws.amis.nl/",
                  wsdlLocation = "http://localhost:7101/...")

@JMSTransportClient (
 targetService = "HelloService",
 destinationName ="com.oracle.webservices.api.jms.RequestQueue",
 replyToName = "com.oracle.webservices.api.jms.ResponseQueue",
 jndiURL ="t3://devagent30:7001",
 jndiInitialContextFactory="com.oracle.webservices.api.jms.ConnectionFactory" ,
 jndiConnectionFactoryName="weblogic.jms.ConnectionFactory" ,
 timeToLive=1000,
 priority=4,
 messageType=JMSMessageType.TEXT)

public class HelloService_Service extends Service {

or as JMSTransportClientFeature in our PortClient class.

JMSTransportClientFeature feature =
  JMSTransportClientFeature.builder()
    .targetService("HelloService")
    .jndiURL("t3://devagent30:7001")
    .destinationName("com.oracle.webservices.api.jms.RequestQueue")
    .replyToName("com.oracle.webservices.api.jms.ResponseQueue")
    .destinationType(JMSDestinationType.QUEUE)
    .messageType(JMSMessageType.TEXT)
    .jndiInitialContextFactory("com.oracle.webservices.api.jms.ConnectionFactory")
    .priority(4)
    .build();

HelloService_Service helloService_Service =
  new HelloService_Service(url,new WebServiceFeature[]{feature});

But the only thing what works for me is changing the SOAP service address location url

like this

HelloService helloService = helloService_Service.getHelloServicePort();

BindingProvider bp = (BindingProvider) helloService;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"jms:jndi:com.oracle.webservices.api.jms.RequestQueue"+
"?targetService=HelloService&"+
"replyToName=com.oracle.webservices.api.jms.ResponseQueue&" +
"jndiURL=t3://devagent30:7001&messageType=TEXT&"+
"deliveryMode=PERSISTENT&priority=4");

System.out.println(helloService.sayHello("hi"));

You can now invoke the JMS Service with proxy client and check the message count on the request and response queue in the WebLogic console.

Here you can look and download my test project.


Friday, July 26, 2013

Maven support in WebLogic & JDeveloper 12.1.2

In the 12.1.2 release of JDeveloper and WebLogic, Oracle really improved the support for Maven as build and provisioning tool. Oracle did this on multiple levels:

  • an Utility to synchronize all the Oracle Middleware jars to a local ( .m2/repository) or a shared repository like nexus or artifactory
  • ojmake maven plugin for just building JDeveloper projects.
  • Updated its Weblogic plugin for deploying artifacts or even creating new WebLogic domains, installing the WebLogic software or running WLST scripts.
  • Coherence plugin for packaging.
  • JDeveloper keeps its application & projects options in sync with the Maven application & projects poms. ( You don't need to lookup all the dependencies jars). 
To get started we need to do the following.

first step is to configure the local Maven settings.

I start with making a maven.sh script or put these variables in the .profile of your build user or set all the windows environments variables which should contain the java_home and set the maven home to the Oracle Middleware Maven home.


export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre
export M2_HOME=/Users/edwin/Oracle/JDevMiddleware12.1.2/oracle_common/modules/org.apache.maven_3.0.4
export PATH=${M2_HOME}/bin:${JAVA_HOME}:$PATH

mvn -v 

We start by synchronizing the local or shared repository.

For this we  need to install a plugin and need to configure the Maven settings.xml which is default located in the .m2 folder of your user home. You can update or create a new settings.xml



When you only use a local repository which located in the .m2 folder we need to do the following steps



1) Install the oracle maven sync plugin to your local repository


cd $ORACLE_HOME/oracle_common/plugins/maven/com/oracle/maven/oracle-maven-sync/12.1.2
mvn deploy:deploy-file -DpomFile=oracle-maven-sync.12.1.2.pom -Dfile=oracle-maven-sync.12.1.2.jar


2) Configure the settings.xml, you need to add the following xml snippet to the settings.xml. This will set all the required maven sync plugin parameters.


 </profiles>
   <profile>
      <id>oracle-maven</id>
      <properties>
        <oracle-maven-sync.oracleHome>/Users/edwin/Oracle/JDevMiddleware12.1.2</oracle-maven-sync.oracleHome>
        <oracle-maven-sync.testOnly>false</oracle-maven-sync.testOnly>
        <oracle-maven-sync.failOnError>false</oracle-maven-sync.failOnError>
      </properties>      
    </profile>  
  </profiles>

  <activeProfiles>
     <activeProfile>oracle-maven</activeProfile>
  </activeProfiles>



3) Test the plugin 

mvn com.oracle.maven:oracle-maven-sync:help


You should see something like this 

When you use a shared Maven repository like nexus or artifactory you need to set this in the settings.xml

1) A Maven mirror with the address of your shared Maven repository and provide all the repositories with its passwords



  <servers>
    <server>
      <id>central</id>
      <username>admin</username>
      <password>password</password>
    </server>
    <server>
      <id>snapshots</id>
      <username>admin</username>
      <password>password</password>
    </server>
    <server>
      <id>artifactory</id>
      <username>admin</username>
      <password>password</password>
    </server>
    <server>
      <id>internal</id>
      <username>admin</username>
      <password>password</password>
    </server>
  </servers>

  <mirrors>
    <mirror>
      <id>artifactory</id>
      <name>Internal artifactory Mirror of Central</name>
      <url>http://hudson:8081/artifactory/repo</url>
      <mirrorOf>*</mirrorOf>
    </mirror>
    
  </mirrors>
  
  <profiles>

    <profile>
      <id>artifactory</id>
      <repositories>
        <repository>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
          <id>central</id>
          <name>libs-release</name>
          <url>http://hudson:8081/artifactory/libs-release</url>
        </repository>
        <repository>
          <snapshots />
          <id>snapshots</id>
          <name>libs-snapshot</name>
          <url>http://hudson:8081/artifactory/libs-snapshot</url>
        </repository>
        <repository>
          <snapshots />
          <id>internal</id>
          <name>libs-snapshot</name>
          <url>http://hudson:8081/artifactory/ext-release-local</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
          <id>central</id>
          <name>plugins-release</name>
          <url>http://hudson:8081/artifactory/plugins-release</url>
        </pluginRepository>
        <pluginRepository>
          <snapshots />
          <id>snapshots</id>
          <name>plugins-snapshot</name>
          <url>http://hudson:8081/artifactory/plugins-snapshot</url>
        </pluginRepository>
      </pluginRepositories>
    </profile>

    <profile>
      <id>oracle-maven</id>
      <properties>
        <oracle-maven-sync.serverId>internal</oracle-maven-sync.serverId>
        <oracle-maven-sync.oracleHome>/Users/edwin/Oracle/JDevMiddleware12.1.2</oracle-maven-sync.oracleHome>
        <oracle-maven-sync.testOnly>false</oracle-maven-sync.testOnly>
        <oracle-maven-sync.failOnError>false</oracle-maven-sync.failOnError>
      </properties>      
    </profile>  
    
  </profiles>
    
  <activeProfiles>
     <activeProfile>artifactory</activeProfile>
     <activeProfile>oracle-maven</activeProfile>
  </activeProfiles>

 

2) Now we can install the sync plugin 


cd $ORACLE_HOME/oracle_common/plugins/maven/com/oracle/maven/oracle-maven-sync/12.1.2
mvn deploy:deploy-file -DpomFile=oracle-maven-sync.12.1.2.pom -Dfile=oracle-maven-sync.12.1.2.jar -Durl=http://hudson:8081/artifactory/ext-release-local -DrepositoryId=artifactory


3) Test the plugin 


mvn com.oracle.maven:oracle-maven-sync:help


The next step is to synchronize the Oracle Middleware home with the local or shared Maven repository

mvn com.oracle.maven:oracle-maven-sync:push

Update the maven catalog

mvn archetype:crawl -Dcatalog=$HOME/.m2/archetype-catalog.xml

With as result. 



We are ready to create some JDeveloper projects with Maven as build tool

JDeveloper keeps the libraries in sync with the project libraries and the pom dependencies.


Also you can add a separate JUnit Test project to this pom, it will do all your unit tests and keeps the code outside your project.


Default this test project should contain JUnit 3 code ( no annotations ) else no test will be executed ( be aware of the Java Class Naming conventions ) .

For JUnit 4 tests you should add the JUnit 4 dependency to the pom.


 
We can also use the maven plugin to do WebLogic actions like appc, create-domain, deploy, distribute-app, install, list-apps, redeploy, start-app, start-server, stop-app, stop-server, undeploy, uninstall, update-app, wlst, ws-clientgen,ws-wsdlc, ws-jwsc

for more information see this Oracle documentation