Pages

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



Thursday, July 25, 2013

JDeveloper 12.1.2 EJB & Java Service Facade Datacontrol

With JDeveloper 12c (12.1.2)  Oracle added some great updates to the ADF EJB / Java Facade Datacontrol. Oracle already added the Java Facade and Named Criteria support in its previous versions of JDeveloper but now also added the so wanted List of Values feature, just like we have in ADF BC.  

In the the next part I will show you all the new features and some LOV bugs ( not everything is working yet )

When we create an EJB DataControl you get besides Range paging also Scrollable as an Access Mode option plus you can immediately generate all the ADF Entity Metadata. 


Just like JDeveloper 11gR2 we can add a Named Criteria to the ADF entity, basically it does the same as a Named Criteria in JPA.



Create a List of Values, select the base entity field ( Selecting the relation entity field won't work, so you need to copy the field and make one of them updatable and insertable ), select the list iterator and the field with matches the field of the base entity.  


Choose the default List Type and all the attributes we want to show in the list type.


We can now use this list type in a Query Panel where we can use it to lookup an manager.




But after selecting an employee then it goes totally wrong, it keeps on looping and tries to get a particular rownum. Also displaying this List item in an ADF Table goes wrong ( it just hangs).  I tried everything from removing all JPA entity relations, adding fetching hints to the JPA named criterias and changing the range size in ADF but all didn't help much.

But it at least it works in a Form page




With this as result


EJB Methods which contains parameters are now also generated as accessor iterators instead of method actions where you need to add method iterators on it. This is a big improvement and keeps the pagedef much cleaner


Accessor iterator

With Execute with params you can pass on the method parameter.


But somehow I did not get this working, I tried the following, first in a page with a parameter form and in bound task flow where I first invoke the execute with params action.


The second part is about the Java Service Facade.  In JDeveloper 12.1.2 the Java Service Facade contains less code and it can update the entity with or without auto commit and without manually calling the merge entity method.


The Persistence unit must be one with Resource Local as Transaction type. You can also choose if you want to do an autocommit.

Next step is generating an ADF Datacontrol on this Java Service Facade



Here we also can choose for Range paging or Scrollable as Access mode.


With a Java Service Facade and an explicit commit we can now also use the rollback or commit button. Plus we don't need to call the mergeEntity method when we change a record.
This is not the case with the EJB datacontrol.

Here you can download or see my example project

Tuesday, June 11, 2013

Custom OSB Reporting Provider

With the OSB Report Action we can add some tracing and logging to an OSB Proxy, this works OK especially when you add some Report keys for single Proxy projects but when you have projects with many Proxies who are invoking other JMS or Local Proxies than the default reporting tables (WLI_QS_REPORT_DATA, WLI_QS_REPORT_ATTRIBUTE ) in the SOA Suite soainfra schema is not so handy.
I want to introduce a conversation id which will be used in all the Proxies and a unique message id for a proxy which will be used in the request and response. Plus it has a status field for the whole conversation ( default = OK, when there is an error somewhere in the conversation then the status will be ERROR)

With this as result. 2 conversations 1 is OK and all matching detail messages ( every proxy has its own messageId so you know which request, response or error belong to each other )
This way I can build my own application which can display all this data, combine this for example with my ErrorHospital data.





The default JMS Reporting part works great for me, so in my Custom Reporting provider I want to re-use the publishing way of the OSB ReportMessage ObjectMessages in the JMS Queue ( wli.reporting.jmsprovider.queue )

So in the next steps I will create a new EJB Application with a Message Driven Bean who reads this ObjectMessage and pass it on to an EJB Session Bean which will use JPA to persist the data in these two tables.

So the first step is to create a new application in JDeveloper and this listener class to the weblogic-application.xml ( located in the src/meta-inf folder of your workspace )
<listener-class>
com.bea.wli.reporting.jmsprovider.init.JmsReportingStartupAndShutdown
</listener-class>

This will enable the OSB Reporting.

You also need plus you need to untarget the default JMS reporing Provider else both applications tries to read the JMS messages.




Add the following jars to your application and uncheck the Export selection ( they are already there on the osb server ). You can find the com.bea.alsb.reporting.api.jar and com.bea.alsb.reporting.impl.jar in your Oracle_OSB1/lib/modules folder of your middleware home



Create a Message Driven Bean


Next step is to tune this MDB so it runs under the ALSBSystem role (ejb-jar.xml ) and in the weblogic-ejb-jar deployment descriptor I set the max and initial pool to 1, this way I can make sure that I have only 1 message record per conversation Id plus this MDB runs as alsb-system-user user.

Add our two JPA entities ( message and message detail ) to the model project and create an EJB session bean with a local interface. This EJB will be invoked by the MDB and pass on the ReportMessage entity.
In the persistence.xml I will reuse the already created wlsbjmsrpDataSource Datasource  ( the message table are also in the soainfra schema )

The EJB session bean does all the heavy work, it needs to determine if the conversation record already exists and retrieve all the Report Action Keys ( message labels).  

Click here to see the EJB Session bean https://github.com/biemond/osb11g_examples/blob/master/CustomOSBReporting/JmsReporting/Model/src/nl/amis/mw/reporting/services/OSBReportingSessionEJBBean.java

Last steps is to make on the project level an EJB deployment ( ejb jar ) and add this to Application deployment profile ( ear ), uncheck the export of all the reporting jars and deploy this to the OSB Server ( must deploy from application menu else the listener class is not loaded )

The last step is to add the report action to all our OSB Proxies

We also need a header element in our message body or header where we can store the conversationId and pass on the other Proxies so every report action can use these values as keys.
In every proxy I first need to add the internal OSB proxy messageID to a variable ( and do not pass it on )  I will do this in the first assign.


This way I can use it in the Request and Response Report Action ( So I know which request ,response or error belong to each other).


In the first Report action I also provided some extra data ( like messagetype, sender, receiver)  this will also be stored in the message table.


In the other proxies I only need to use the Conversation Id and the messageId of that proxy.


In the Error handler I also added a report action so I know what the error is and set the status of the message to ERROR



That's all for the custom reporting part. Off course you can add extra field to these tables by adding your own report keys. You only need to change the EJB and the JPA Entities.

Here you can find all the code together with an OSB demo workspace.
https://github.com/biemond/osb11g_examples/tree/master/CustomOSBReporting