Wednesday, December 18, 2013

How to zip/base64 string response on Oracle Service Bus

How to zip/base64 string response on Oracle Service Bus


                When you are working with huge results like big XMLs or Json  is handy to compress the OSB output. As an example if you are connecting to an Android device you can send the data compressed and then let Android decompress it.

Here is an example of how to accomplish this task in Oracle Service Bus.

1.    1.   First we need to create a class that will compress a String.

public class ZipContent {
    public ZipContent() {
        super();
    }

    public static String zipme(String content) throws IOException {


        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        gzip.write(content.getBytes());
        gzip.close();

        byte[] bytes = out.toByteArray();
        return  Base64.encodeBase64String(bytes);
       
    }
}

2.       2. Add your library to a jar file and add it in the resource folder of your Service Bus project
3.      3. Create a new java callout with your body

Method: ZipContent.zipme
Expression: $body
Result value: body









4.    4.   Your results will be compresses and in base64



Tuesday, November 12, 2013

AQ burst in OSB and notification in BPEL when burst is complete

Create Maximum Thread Constraints


11. On weblogic console Navigate to Environment > Work Managers > New

22.  Define a new maximum threads constraint
3. Define the count number to two


Create a work Manager

11.   Navigate to Environment > Work Managers New
22.   Select work manager

3. Add a name to the work manager
14. Add the server targets that will use the work manager and click finish
25. After created select it from the work managers list

16. Assign the maximum threads constraint option


BPEL notification process


For this BPEL process we are going to use a pattern call aggregation with correlation sets. Basically we are going to correlate all the bpel processes using a batchid and after 15 seconds of not receiving aq messages the process will be closed so we can notify the client that all invoices are consumed.

11.  Create a new schema accepting two parameters an invocieid and batch. Batch is the value that will be used as correlation





12. Create a one way process passing the “request” of the schema as input
23.  BPEL process will  have the following characteristics
a.       Create a while loop when a variable call count < 1
b.      Initialize variable count with 1
c.       Create a pick, If you receive a new message use correlation batch explained in next step
d.      If no more requests are received timeout adding count as value of 1
                                                               i.      In this step you  can add the notification to the customer

14. To create a correlation go the left bar as show in screen and click add

15. Create a correlation naming it “correlationAggregate” add a new property with Name “batch” and string type.    
a.       Assign the received message as the request type and query to bath element of the schema as shown in the screenshot
16. Make sure that “Create Instance” is checked on the receiveInput .

7. Add the correlation set to the “receiveinput” and set the property Initiate to “yes”


18. Add the correlation se to the “onMessage” setting the property initiate to “no”


BPEL process with wait


11. Create a synchronous process that will have the following activites
a.       Call the BPEL notification process
b.      Call a wait of 3 seconds only to see the dealy on each process



OSB burst program


1.1. Create a new proxy service that will call the sync wait process created in the previous step. This proxy service requires to have the following
a.       Throttling state enabled
b.      Maximum concurrency 2
c.       Throttling queue  2


12.  Create a dequeue business service  and cal the service created in step 1
a.       Make sure to add the work manager “wm/aqconsumer”  in the dispatch policy



1.3.  Business service will look like this
a.       Make sure to pass the batch id always the same during the burst



Results

                Disable the OSB process, enqueue some messages


You will see that every 2 seconds 2 processes are picked up and triggered. Also the aggregate process will continue stop and send a notification 15 seconds after the last message is received.









Wednesday, November 6, 2013

How to ssh with no password


1.      1.  ssh-keygen –t rsa on server1
hit return on password
2.      2.  ssh-copy-id –I .ssh/id_rsa.pub user@server2
3.       3. on server2
a.       chmod 700 .ssh
b.      chmod 640 .ssh/authorized_key
4.      4. Finally you can test it ssh user@server2

Thursday, October 17, 2013

How to configure OAF environment

1.      Set a local variable JDEV_HOME to your jdeveloper installation in my scenario is “G:\jdevoa\jdevhome\jdev”
2.      Go to $FND_SECURE and copy your environment “.dbc” file into your  local environment “$JDEV_HOME\..\..\jdevbin\oaext\dbc_files\secure\FILE.dbc”
3.      Right click on the application and Create a “New OA Workspace”


1.      Select a name for your workspace and make sure that is pointing to $JDEV_HOME\jdev

1.      Select a project name check the option “Use repository at design time” and create a new database connection








1.      On the File Name click browse and select the dbc file that you copied in step 2
a.      Populate your user name , password, application short name and responsibility key
2.      Copy the code you want to modify from the following locations
a.      $AP_TOP/MDS to jdevhome/myprojects
b.      $JAVA_TOP to jdevhome/jdev/myclasses
3.      Refresh your project

1.      Click on the page you want to execute



1.      Depending of what page and what code are you executing is the time that will take to run, it can take a long time so be prepared



Wednesday, September 18, 2013

Using Google App Engine Endpoints and JPA to interact with data

The following example assumes you have a google account, have downloaded GAE (Google App Engine) dev kit and eclipse plugin.  The goal is to show how to create a Google End Point interface that interacts with records in google datastore thru JPA. Our example shows a car catalog which persists "Car" objects and has a method to query all of them too. The classes to be created are

Car.java -> represents an Entity within google datastore
EMF.java -> represents a static class to generate Entity Manager Factory.
CarHandler.java -> Acts as a controller between the End Point and the datastore.
CarEndPoint.java -> Implements the Car google API endpoint.

The following diagram shows up the classes and their relationships


Step 1
Create a new Google Web App within eclipse as follows

After generating your project make sure to include the following jars related to JPA within the directory WAR/WEB-INF/lib.  All of these can be obtained from the lib directory where app engine is installed.



Step 2
Generate the code for the Car Entity, note the annotations show how this pojo becomes a datastore entity
package com.salamander.cars;

import javax.persistence.Entity;
import com.google.appengine.api.datastore.Key;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Car {

private String brand;
private String model;
private Integer year;
@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
public Key getKey() {
        return key;
    }
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}

}

Step 3
Generate the entity manager factory class EMF.java
package com.salamander.cars;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public final class EMF {
    private static final EntityManagerFactory emfInstance =
        Persistence.createEntityManagerFactory("transactions-optional");

    private EMF() {}

    public static EntityManagerFactory get() {
        return emfInstance;
    }
}

Step 4
Generate the Controller aka CarHandler.java. This class implements 2 methods, one to insert new records to the datastore and another to retrieve all the records within it.  Note the use of JPA packages.

package com.salamander.cars;

import java.util.List;

import javax.persistence.EntityManager;

public class CarHandler {

public void addCar(String _sBrand, String _sModel, int _iYear){

Car car = new Car();
car.setBrand(_sBrand);
car.setModel(_sModel);
car.setYear(new Integer(_iYear));

EntityManager em = EMF.get().createEntityManager();
em.getTransaction().begin();
em.persist(car);
em.getTransaction().commit();

}

public List<Car> getAllCars(){

EntityManager em = EMF.get().createEntityManager();
em.getTransaction().begin();
List<Car> result = em.createQuery( "select car from Car car", Car.class ).getResultList();

em.getTransaction().commit();

return result;
}

}

Step 5
Generate the actual endpoint class CarEndPoint.java.  This API exposes 2 API Methods car.add and readall. The first one follows the pattern car/add/{brand}/{model}/{year} to add a new car to the datastore. Whereas the pattern for the second API method is just readall.

package com.salamander.cars;

import java.util.List;
import javax.inject.Named;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;

@Api(name = "car"
, version = "v1"
, clientIds = {com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID}
, audiences = {"vehiclecarx.appspot.com"}
, scopes = {"https://www.googleapis.com/auth/userinfo.email"}
)
public class CarEndPoint {

@ApiMethod(name = "car.add"
, path = "car/add/{brand}/{model}/{year}"
, httpMethod = HttpMethod.PUT)
public void addCar(@Named("brand") String _sbrand
, @Named("model") String _smodel
, @Named("year") String _syear) {
 
CarHandler ch = new CarHandler();
ch.addCar(_sbrand, _smodel, Integer.parseInt(_syear));
}  

// url -->  https://vehiclecarx.appspot.com/_ah/api/car/v1/readall
// sample url --> https://vehiclecarx.appspot.com/_ah/api/car/v1/readall?fields=items(brand%2Cmodel%2Cyear)
@ApiMethod(name = "readall"
, path = "readall"
, httpMethod = HttpMethod.GET)
public List <Car> readall(){

CarHandler ch = new CarHandler();
List<Car> cars = ch.getAllCars();
 
    return cars;
}
}

Last but not least tthree things are missing here.  Set up your app web.xml file, setup persistence.xml file and create your google app id.  Web.xml should look as below

<?xml version="1.0" encoding="utf-8" standalone="no"?><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  
 <servlet>
  <servlet-name>SystemServiceServlet</servlet-name>
  <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
  <init-param>
   <param-name>services</param-name>
   <param-value>com.salamander.cars.CarEndPoint</param-value>
  </init-param>
 </servlet>
 <servlet-mapping>
  <servlet-name>SystemServiceServlet</servlet-name>
  <url-pattern>/_ah/spi/*</url-pattern>
 </servlet-mapping>
</web-app>

persistence.xml file should be located in the directory war/WEB-INF/META-INF and should look as

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

    <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
        <properties>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" value="true"/>
            <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
    </persistence-unit>
</persistence>

The google application id can be generated in google administration console (URL  https://appengine.google.com/).  And just like any other GAE project when deploying tie your app to the id you created within your account in GAE console.

After deploying you should be able to use google's apis explorer and test your scenarios.  In my case my google api explorer corresponds to https://developers.google.com/apis-explorer/?base=https://vehiclecarx.appspot.com/_ah/api#p/

and shows as 

Click on any of the exposed methods and happy testing.  Below is the result after testing the readall method. Note how google shows the url you could use in your clients to call any of the exposed APIs.










Monday, September 16, 2013

How to fix " Problem: failed to create task or type if" when building ant on Middleware/Oracle_SOA1/soa/modules/oracle.soa.ext_11.1.1


Download the code from http://sourceforge.net/projects/ant-contrib/files/

Finally add the following lines to the task files

<taskdef resource="net/sf/antcontrib/antcontrib.properties">
  <classpath>
    <pathelement location="[downloaded path]/ant-contrib-1.0b3.jar"/>
  </classpath>
</taskdef>



Execute ant and issue will be fixed

Thursday, September 12, 2013

Add file name to Instance name using composites (mediator)


Sometimes is required to have the file name that we are pooling in our composite, we can achive that with a simple assign function in the mediator

1. Create an assign element

2. Add the following "expression" to from

med:setCompositeInstanceTitle($in.property.jca.file.FileName)

3. In the "properties "to add the following:

tracking.compositeInstanceTitle

Note: this properties is not shown in the list


Thursday, September 5, 2013

Create a PGP decryption pipeline Valve in Oracle SOA suite 11g




 SOA suite provides a way to do file preprocessing. In this particular scenario we will create a valve that uses PGP private key to decrypt an encrypted file.
               If you required additional information about oracle pipelines please review the following link
              
We are going to use bouncy castle as main PGP library
And this code as reference

A.     Java Valve code


1.      1. Create a new project in JDev adding the following libraries


Bpm-infra should be on your SOA Suite installation ./Oracle_OSB1/soa/modules/oracle.soa.fabric_11.1.1/bpm-infra.jar
Bcpg-jdk15on-19.jar, bcprov-ext-jdk15on-149.jar and bcprov-jdk15on-149.jar you can download them from bouncy castle website.
2.     2.  Create a properties file that will indicate where your key and passphrase are, add it to Jdev

#properties file for PGP decrypt file
privatekey=/home/oracle/work/aaronkey.gpg
passphrase=welcome1

3.      3. Create the following code

package something;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.util.Properties;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import oracle.tip.pc.services.pipeline.AbstractValve;
import oracle.tip.pc.services.pipeline.InputStreamContext;
import oracle.tip.pc.services.pipeline.PipelineException;

public class DecryptPGPValve extends AbstractValve {
    public DecryptPGPValve() {
        super();
    }


    public InputStreamContext execute(InputStreamContext inputStreamContext) throws PipelineException,
                                                                                    IOException {
        Properties props = new Properties();
        try {
            props.load(DecryptPGPValve.class.getResourceAsStream("/resource.properties"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        PGPFileProcessor pgp = new PGPFileProcessor();

        pgp.setSecretKeyFileName(props.getProperty("privatekey")); // can be either binary or text key
        pgp.setPassphrase(props.getProperty("passphrase"));


        byte[] encrypted = null;

        try {
            encrypted = pgp.decrypt(inputStreamContext.getInputStream());
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        inputStreamContext.setInputStream(new ByteArrayInputStream(encrypted));

        return inputStreamContext;
    }

    public void finalize(InputStreamContext inputStreamContext) {
    }

    public void cleanup() throws PipelineException, IOException {
    }
}
   

4.      4. From the code provided by bouncy castle modify the decrypt method to return bytes
Something like this (check lines in red)

    /**
     * decrypt the passed in message stream
     */
    @SuppressWarnings("unchecked")
        public static byte[] decryptFileBytes(InputStream in, InputStream keyIn, char[] passwd)
        throws Exception
    {
    
        byte[] encrypted = null;
        Security.addProvider(new BouncyCastleProvider());

        in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);

        PGPObjectFactory pgpF = new PGPObjectFactory(in);
        PGPEncryptedDataList enc;

        Object o = pgpF.nextObject();
        //
        // the first object might be a PGP marker packet.
        //
        if (o instanceof  PGPEncryptedDataList) {
            enc = (PGPEncryptedDataList) o;
        } else {
            enc = (PGPEncryptedDataList) pgpF.nextObject();
        }

        //
        // find the secret key
        //
        Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;

        while (sKey == null && it.hasNext()) {
            pbe = it.next();

            sKey = findPrivateKey(keyIn, pbe.getKeyID(), passwd);
        }

        if (sKey == null) {
            throw new IllegalArgumentException("Secret key for message not found.");
        }

        InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));

        PGPObjectFactory plainFact = new PGPObjectFactory(clear);

        Object message = plainFact.nextObject();

        if (message instanceof  PGPCompressedData) {
            PGPCompressedData cData = (PGPCompressedData) message;
            PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream());

            message = pgpFact.nextObject();
        }


        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final DataOutputStream dos = new DataOutputStream( baos );
              

        if (message instanceof  PGPLiteralData) {
            PGPLiteralData ld = (PGPLiteralData) message;

            InputStream unc = ld.getInputStream();
            int ch;

            while ((ch = unc.read()) >= 0) {
                //out.write(ch);
                dos.write(ch);
            }
           
            dos.close();
            encrypted = baos.toByteArray();
            baos.close();
                       
        } else if (message instanceof  PGPOnePassSignatureList) {
            throw new PGPException("Encrypted message contains a signed message - not literal data.");
        } else {
            throw new PGPException("Message is not a simple encrypted file - type unknown.");
        }

        if (pbe.isIntegrityProtected()) {
            if (!pbe.verify()) {
                throw new PGPException("Message failed integrity check");
            }
        }
        System.out.println("decode:" + encrypted);
        return encrypted;
    }
5.    5.  Compress your files in a JAR file and place them in
/home/oracle/Oracle/Middleware/Oracle_SOA1/soa/modules/oracle.soa.ext_11.1.1
/home/oracle/Oracle/Middleware/user_projects/domains/base_domain/lib

Directories might change

6.      6. Add bouncy castle libraries as well
Bcpg-jdk15on-19.jar, bcprov-ext-jdk15on-149.jar and bcprov-jdk15on-149.jar in the following directories

/home/oracle/Oracle/Middleware/Oracle_SOA1/soa/modules/oracle.soa.ext_11.1.1
/home/oracle/Oracle/Middleware/user_projects/domains/base_domain/lib

7. Bounce your server and let’s continue working on the composite

b. Composites


Our idea is to create a composite that will read a file from file system and will decode it another directory. This can be easily replace with FTP adapter and work as well.




1.      1. Create a PollFile adapter
a.      Is important to uncheck the Use file streaming option
b.      Use native format opaque
2.    2.    Create a “filePipeline.xml” file in Jdeveloper as following

<?xml version="1.0"?>
<pipeline xmlns="http://www.oracle.com/adapter/pipeline">
<valves>
        <valve>us.myvalve.com.ebs.encryption.gpg.DecryptPGPValve</valve>
</valves>
</pipeline>

3.      3. Open the poll jca file and add the pipeline property

<adapter-config name="PollFile" adapter="File Adapter" wsdlLocation="PollFile.wsdl" xmlns="http://platform.integration.oracle/blocks/adapter/fw/metadata">
 
  <connection-factory location="eis/FileAdapter" UIincludeWildcard="test*.pgp"/>
  <endpoint-activation portType="Read_ptt" operation="Read">
    <activation-spec className="oracle.tip.adapter.file.inbound.FileActivationSpec">
      <property name="DeleteFile" value="true"/>
      <property name="MinimumAge" value="0"/>
      <property name="PhysicalDirectory" value="/home/oracle/work/files"/>
      <property name="Recursive" value="false"/>
      <property name="PollingFrequency" value="10"/>
      <property name="PhysicalArchiveDirectory" value="/home/oracle/work/archive"/>
      <property name="IncludeFiles" value="test.*\.pgp"/>
      <property name="UseHeaders" value="false"/>
      <property name="PipelineFile" value="filePipeline.xml"/>
    </activation-spec>
  </endpoint-activation>

</adapter-config>

4.     4.  Create a write sync operation file


Your decryption should be ready to test