Compilation issues Java sources and Oracle BPEL

Compilation issues Java sources and Oracle BPEL

Published on: Category: Java & Web

When building a SOA project we can have multiple different components to be build. One of them is the BPEL process itself. In this article we’ll discuss this compilation process using ant. The trigger for this was error during one of our build processes.

I recently ran into the following issue whilst compiling a BPEL process from our build server:

scac:
[scac] Validating composite "/build/MyBPEL/composite.xml"

[scac] package mypackage does not exist
[scac] cannot find symbol
[scac]   symbol:   variable MyClass
[scac]   location: class orabpel.MyBPEL.ExecLetBxExe3

 [scac] /build/MyBPEL/composite.xml:29: error: Instantiation exception for implementation type "implementation.bpel", validating component "MyBPEL". Exception is "Failed to compile bpel generated classes.

[scac] failure to compile the generated BPEL classes for BPEL process "MyBPEL" of composite "default/MyBPEL!1.0"

[scac] The class path setting is incorrect.
[scac] Ensure that the class path is set correctly. If this happens on the server side, verify that the custom classes or jars which this BPEL process is depending on are deployed correctly. Also verify that the run time is using the same release/version.
[scac] "

BUILD FAILED

It compiled properly from JDeveloper? But when building from the build server it suddenly fails!

BPEL process

The issue occurred in a BPEL process with some inline Java (fig 1). The inline Java itself (fig 2) uses a custom Java class (fig 3) which is enclosed in the project, as a project source (fig 4).

Figure 1 - Java Embedding in BPEL diagram:

Figure 2 - Java Embedding in BPEL source:

  1. <bpelx:exec import="mypackage.MyClass"/>
  2. <bpelx:exec name="PerformJavaLogic" version="1.5" language="java">
  3. <![CDATA[
  4. XMLElement myData = (XMLElement) getVariableData("MyTransformedResponse", "payload", "//ns1:Result");
  5. String myTransformedResponse = myData.getText();
  6. // Do some complicated logic from another Java class in this project
  7.  
  8. String javaResultData = MyClass.doComplexLogic(myData );
  9. setVariableData("MyResultResponse", "body", "//ns2:ResultResponse” javaResultData );
  10. ]]>
  11. </bpelx:exec>
  12.  

Figure 3 - Java Source code:

  1. package mypackage.MyClass;
  2. public Class mypackage.MyClass {
  3. public String doComplexLogic( String myData ) {
  4. // do complex logic
  5. }
  6. }
  7.  

Figure 4 - Setting up Java source path

Source folders

Oracle JDeveloper seems to do a Java compile on all ‘source folders’, just before compiling the BPEL itself. When building from JDeveloper we see the following in the logs, before the BPEL compilation itself:

Context: BuildProjectAndDependenciesCommand selection=MyBPEL.jpr application=SOAWorkspace.jws project=MyBPEL.jpr node=MyBPEL.jpr

C:\jdk\bin\javac -g -Xlint:all -Xlint:-cast -Xlint:-empty -Xlint:-fallthrough -Xlint:-path -Xlint:-serial -Xlint:-unchecked -source 1.6 -target 1.6 -verbose -encoding Cp1252 -classpath C:\jdk\jre\lib\resources.jar;C:\jdk\jre\lib\rt.jar;C:\jdk\jre\lib\jsse.jar;C:\jdk\jre\lib\jce.jar;C:\jdk\jre\lib\charsets.jar C:\Myproject\MyBPEL\SCA-INF\lib\mylibrary-1.1.0.jar -sourcepath C:\Myproject\MyBPEL\src -d C:\Myproject\MyBPEL\SCA-INF\classes C:\Myproject\MyBPEL\src\mypackage\MyClass.java

Compiling 1 source

  Compiling C:\Myproject\MyBPEL\src\mypack\MyJava.java
Round 1:
                input files: { mypack. MyJava }
                annotations: []
                last round: false
Round 2:
                input files: {}
                annotations: []
                last round: true

  Writing C:\Myproject\MyBPEL\SCA-INF\classes\ mypack \ MyJava.class
 [2:29:58 PM] Compilation complete: 0 errors, 26 warnings.

Oracle's own package

From the ant build logs on the build server we have concluded that our automated build script did not perform this compilation first! 

Our automated build script makes use of Oracle’s own package/compilation ant build files: ${soa.dir}/bin/ant-sca-package.xml

In our script we loop through all projects. In figure 5 we only shows our call to Oracle’s ant-sca-package.xml build file.

Figure 5 - Ant script for building and packaging an Oracle SOA project:

  1. <echo>Create package</echo>
  2. <ant antfile="${oracle.home}/bin/ant-sca-package.xml" inheritAll="false" target="package">
  3.     <property name="scac.application.home" value="${adfconfigbasedir}"/>
  4.     <property name="compositeName" value="${compositeName}"/>
  5.     <property name="revision" value="${revision}"/>
  6. </ant>

Our script invokes ant target package which depends on target scac-validate (see fig 6):

Figure 6 - Example of ant-sca-package.xml:

  1. <target name="package" depends="scac-validate">
  2. <!-- compile source if any -->
  3. <available file="${src.dir}" type="dir" property="compile.source"/>
  4. <antcall target="compile-source"/>
  5.  

This SCA validation does not do any compile, but will check the BPEL composite. In case the BPEL composite depends on the compilation of a Java source file, it will fail!

What we need is to compile any Java sources first before calling this package target. Oracle has a script for that, in the ant-sca-package.xml as well. You probably already have noticed the ant call for target “compile-source” (fig 6).

Summarizing

  1. The target package depends on scac-validate, which in our opinion is called too early.
  2. As one of the first steps we see the package target calls another ant target called “compile-source”.
  3. What we need to do is to call this ‘compile-source’ target before we call target ‘package’.

Resolution

Before calling the “package” target in ${soa.dir}/bin/ant-sca-package.xml we will call the “compile-source” target first. Figure 7 shows the compile-source target which is called by the package target code from figure 8. Please notice, before calling “compile-source”, we also need to set the property ‘compile.source’ which is a prerequisite. In addition we see we need to verify whether there exists a /src folder first, before calling the compile (see fig 8).

Figure 7 - Example of ant-sca-package.xml: compile-source target:

  1. <target name="compile-source" if="compile.source">
  2. <echo message="deleting .class files of ${sca-inf.classes.dir}"/>
  3. <delete includeemptydirs="true" failonerror="false">
  4. <fileset dir="${sca-inf.classes.dir}" includes="**/*.class" excludes="**/package-info.class"/>
  5. </delete>
  6. <mkdir dir="${sca-inf.classes.dir}"/>
  7. <touch>
  8. <fileset dir="${src.dir}" includes="**/package-info.java"/>
  9. </touch>
  10. <javac srcdir="${src.dir}" classpathref="scac.tasks.class.path" destdir="${sca-inf.classes.dir}" debug="true">
  11. </javac>
  12. </target>
  13.  

Figure 8 - Example of ant-sca-package.xml: check for /src folder and setting property:

  1. <!-- compile source if any (unset first) -->
  2. <available file="${src.dir}" type="dir" property="compile.source"/>
  3. <antcall target="compile-source"/>
  4.  

Modifications

In our script we have made the following modifications:

  1. Unset the compile.source property:  because we are looping through multiple projects, and we like to use this property as a variable (see fig 9).
  2. Create a small wrapper ant target (see fig 10): compileProject
    • Make sure to call Oracle’s compile-source target correctly
  3. Call this compileProject target from your main build script just before calling Oracle’s ‘package’ target (see fig 9).

Figure 9 - Ant code for checking source dir and (un)setting property. To be added just before calling Oracle’s package target:

  1. <var name="compile.source" unset="true"/>
  2. <available file="${svn.soa.dir}/@{line}/src" type="dir" property="compile.source"/>
  3. <antcall target="compileProject" inheritall="true">
  4. <param name="compositeDir" value="${svn.soa.dir}/@{line}" />
  5. </antcall>

Figure 10 - Ant target (wrapper) for calling Oracle’s compile-source target:

  1. <target name="compileProject" if="compile.source">
  2. <ant antfile="${soa.dir}/bin/ant-sca-package.xml" inheritAll="false" target="compile-source">
  3. <property name="scac.application.home" value="${svn.ci.dir}/tmp"/>
  4. <!--location of the adf-config.xml file -->
  5. <property name="compositeDir" value="${compositeDir}" />
  6. <property name="compositeName" value="${changedProject}"/>
  7. <property name="revision" value="${revision}"/>
  8. <property name="compile.source" value="true"/>
  9. </ant>
  10. </target>

Using this change we were able to compile the Java sources first, before compiling and packaging the BPEL.

Richard Velden
About the author Richard Velden

Oracle Fusion Middleware Developer at Qualogy. Specializes in integration and cloud development using Oracle technologies such as: SOA Suite, Service Bus, Integration and Process Cloud.

More posts by Richard Velden