Skip to Content
Technical Articles
Author's profile photo stephen xue

JAXB in SAP PI Java Mapping

There were few blogs on this topic written before year 2013. Whereas after the IDE eclipse has been updated with many new versions and SAP PI platform has updated, the user interfaces have changed accordingly. Newcomers may find it a bit hard to follow the process by using the old blogs.

Let’s refresh the memory. Good technology is worth to be updated. Here are the steps in the new updated platforms.

1 Setup Eclipse for JAXB

To do so select Help -> Install New Software… from the eclipse main menu bar

 

For my version, access is

Neon – http://download.eclipse.org/releases/neon

After install the add-ons, restart the NWDS

These extra options can be viewed in the start wizard

2 Start PI JAVA mapping

2.1 Get source and target XSD

of course, you can create/use whatever message types you want according to the requirement. here in my example, the message structures are:

source:

 

Target:

2.2 Create JAXB class in NWDS

2.3 Create packages

Create one source package, one target package and one main package

Import the xsd file into the package respectively

2.4 Generate message class

Right click on the XSD file and choose newàotheràJAXBàJAXB classes from schema

Click Next button

Information in the Console tab showing some java classes have been generated.

Follow the same steps to generate classes for target schema. When both schemas have been processed the project explorer is like this

 

2.5 Develop Java Mapping

Add SAP java library to the project and create the mapping class

Here is the source code of the class together with the unit test. please be notified that part of the namespace has been replaced by <dummy>. please replaced it by using any hostname making sense.

package au.com.<dummy>.jaxb.test02;

import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import au.com.<dummy>.jaxb.test02.CRM_CustomerInformation_to_ERP_UserCollection;
import au.com.<dummy>.jaxb.test02.source.CustomerInformation;
import au.com.<dummy>.jaxb.test02.target.ExtraInfo;
import au.com.<dummy>.jaxb.test02.target.UserCollectionMessage;
import au.com.<dummy>.jaxb.test02.target.UserRecord;
import au.com.<dummy>.jaxb.test02.source.CustomerInformation.Customer;
import au.com.<dummy>.jaxb.test02.target.ObjectFactory;

public class CRM_CustomerInformation_to_ERP_UserCollection extends AbstractTransformation {

	@Override
	public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException {
		// TODO Auto-generated method stub
		 getTrace().addInfo("JAVA Mapping JAXB_Mapping is Initiated");
		 this.execute(in.getInputPayload().getInputStream(), out.getOutputPayload().getOutputStream());
	}
	
	public void execute(InputStream in, OutputStream out)  throws StreamTransformationException {
		 try {
			 InputStream is = in;
             JAXBContext jaxbContext = JAXBContext.newInstance(CustomerInformation.class);
             Unmarshaller unMarshaller = jaxbContext.createUnmarshaller();
             
             JAXBElement<CustomerInformation> customerInforamtion = (JAXBElement<CustomerInformation>) unMarshaller.unmarshal(new StreamSource(is), CustomerInformation.class);
             getTrace().addInfo("Unmarshall Successful");
             
             /*————- Marshal the Target—————-*/
             
             ObjectFactory objectFactory = new ObjectFactory();
             UserCollectionMessage userCollectionMessage = objectFactory.createUserCollectionMessage();
             JAXBElement<UserCollectionMessage> target = objectFactory.createUserCollection(userCollectionMessage);
             for (int i = 0; i < customerInforamtion.getValue().getCustomer().size(); i++){
            	 UserRecord user = objectFactory.createUserRecord();
            	 Customer customer = customerInforamtion.getValue().getCustomer().get(i);
            	 user.setFirstname(customer.getGivenname());
            	 user.setLastname(customer.getSurname());
            	 user.setFullname(customer.getGivenname()+" "+customer.getSurname());
            	 user.setUsername(customer.getGivenname()+"_"+customer.getSurname());
            	 
            	 ExtraInfo extraInfo = objectFactory.createExtraInfo();
            	 extraInfo.setAddressLine1(customer.getAddress().getLine1());
            	 extraInfo.setAddressLine2(customer.getAddress().getLine2());
            	 extraInfo.setAddressLine3(customer.getAddress().getLine3());
            	 extraInfo.setCity(customer.getAddress().getState());
            	 extraInfo.setPostCode(customer.getAddress().getPostcode());
            	 extraInfo.setDateOfBirth(customer.getDOB());
            	 extraInfo.setEmailAddress(customer.getContact().getEmail());
            	 extraInfo.setMobile(customer.getContact().getMobile());
            	 
            	 user.setExtraInfo(extraInfo);
            	 userCollectionMessage.getUser().add(user);
             }
             
             JAXBContext contextTarget = JAXBContext.newInstance(UserCollectionMessage.class);
             Marshaller marshallerTarget = contextTarget.createMarshaller();
             marshallerTarget.marshal(target, out);
		 }catch (Exception e) {
			 e.printStackTrace();
		 }		
	}
	public static void main(String[] args) {
	       String srcMsgFileName = "src/source.xml";
	       String tgtMsgFileName = "src/target.xml";
	       try {
	    	   	InputStream 	in  = new FileInputStream(new File(srcMsgFileName));
	    	    OutputStream 	out = new FileOutputStream(new File(tgtMsgFileName));
	    	    CRM_CustomerInformation_to_ERP_UserCollection 	myMapping = new CRM_CustomerInformation_to_ERP_UserCollection();
	    	    myMapping.execute(in, out);
	            System.out.println("Mapping test completed successfully");
	       } catch (Exception e) {
		       System.err.println("Mapping test failed");
		       e.printStackTrace();
	       }
	  }
}

By using the generated message classes, the syntax is easy to be read and its logic is straightforward comparing with DOM or SAX.

2.6 Export the program into JAR and import it to SAP PI

Since the source java files are coming from three different packages, these packages all should be selected and exported to avoid syntax error in SAP PI

After imported, the classes list in the imported archive is like this

3 Unit Test

This is the test conducted in the operation mapping

Check the target message. The mapping program handled namespace by itself.

 

4 Reference

https://rocksolutions.blog/2010/08/04/sample-on-jaxb-using-eclipse/

https://blogs.sap.com/2012/02/07/forget-sax-and-dom-java-mapping-just-got-cooler-with-jaxb-part-2/

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Roy Berby
      Roy Berby

      Thank you for the great guide.

      When executing my java mapping in the PI during the execution of:
      JAXBContext jaxbContext = JAXBContext.newInstance([class_name].class);
      the program throws an error containing only "null"

      When attempting to use class'es context path instead:
      JAXBContext jaxbContext = JAXBContext.newInstance([class_name].class.getPackage().getName(););
      The PI asks for a jaxb.properties file

      Do you have any idea?

      Author's profile photo stephen xue
      stephen xue
      Blog Post Author

      Hi Roy

      have you import class_name to your program?

      for instance, when the following statement has been written

      JAXBContext jaxbContext = JAXBContext.newInstance(CustomerInformation.class);

      The class CustomerInformation has to be generated by JAXB from the XSD and imported to the program

      import au.com.<host>.jaxb.test02.source.CustomerInformation;

      On the other hand, if your xsd does contain any referenced types, please check the tutorial below to be parsed via a catalog file. Make sure your eclipse has internet connection.

      http://blog.bdoughan.com/2011/10/jaxb-xjc-imported-schemas-and-xml.html