Skip to Content

In this blog, I would like to share my recent experience with Graphical mapping in regards to having java mapping in it

For those who don’t know the concept of ‘having a java mapping within graphical mapping‘, please check Sunil Chandra‘s blog: Write Java Mapping directly in ESR!

We can also call graphical mapping using super.transform(TransformationInput in, TransformationOutput out) method from same graphical mapping as per  Daniel Graversen‘s blog: Hacking: To get error from the PI Mapping Mapping realtime.

So now the question is, can we club the above ‘two blog concepts in a single graphical mapping’ ?

(or)

Rather I would say, ‘can we have below operation mapping patterns in a single graphical mapping’ ?

Pattern1:

1) JavaMapping 2) GraphicalMapping

Pattern2:

1) GraphicalMapping 2) JavaMapping

Pattern3:

1) JavaMapping One 2) GraphicalMapping 3) JavaMapping Two

Well, it is not possible directly, and this is where this blog comes into picture

The solution is, we should override standard TransformationInput, TransformationOutput, InputPayload and OutputPayload classes with our own implementation code.

With a little bit experimentation I am able to achieve above patterns in a single graphical mapping. Please note that, the java code should be put under Graphical mapping –> Functions –> ‘Attributes and Methods’ section.

Please use only required pattern and remove/comment the rest of patterns as per your needs

Java Code:-


InputAttachments inputAttachments;
InputHeader inputHeader;
InputParameters inputParameters;
DynamicConfiguration dynamicConfiguration;
OutputAttachments outputAttachments;
OutputHeader outputHeader;
OutputParameters outputParameters;
public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException{
  try
  {
  dynamicConfiguration = in.getDynamicConfiguration();
  inputAttachments = in.getInputAttachments();
  inputHeader = in.getInputHeader();
  inputParameters = in.getInputParameters();
  outputAttachments = out.getOutputAttachments();
  outputHeader = out.getOutputHeader();
  outputParameters = out.getOutputParameters();
  InputStream is = (InputStream) in.getInputPayload().getInputStream();
  /*
  * **************************** GuideLines for Java Mapping ********************************************************************
  * You can have java mapping code INLINE if it is few lines. And if it is a big and complex code, then I recommend to isolate
  * java mapping logic and develop it separately as a NORMAL java program. Import it as 'imported archive' and refer it in graphical mapping
  * And then call the externally developed public method here
  * Recommendation for external method signature: public ByteArrayOutputStream YourExtBussLogicMethod(InputStream is, ...)
  * **********************************************************************************************************************************
  */
  /*BEGIN ************************************************* PATTERN 1 (JM - GM) **************************************************/
  //Java Mapping: YourExtBussLogicMethod(is) code is nothing but your java mapping logic. You can also have INLINE code here
  ByteArrayOutputStream baos = YourExtBussLogicMethod(is);
  InputStream newInputStream = new ByteArrayInputStream(baos.toByteArray());
  InputPayloadImpl payloadInObj = new InputPayloadImpl(newInputStream);
  TransformationInputImpl transformInObj = new TransformationInputImpl(payloadInObj);
  //Graphical mapping called here
  super.transform(transformInObj, out);
  /*END ************************************************* PATTERN 1 (JM - GM) **************************************************/
  /*BEGIN ************************************************* PATTERN 2 (GM - JM)  **************************************************/
  InputPayloadImpl payloadInObj = new InputPayloadImpl(is);
  TransformationInputImpl transformInObj = new TransformationInputImpl(payloadInObj);
  OutputStream os = new ByteArrayOutputStream();
  OutPayloadImpl payloadOutObj = new OutPayloadImpl(os);
  TransformationOutputImpl transformOutObj = new TransformationOutputImpl(payloadOutObj);
  // Graphical mapping called here, but the transformed stream is written to intermediate ByteArrayOutputStream 'os'
  super.transform(transformInObj, transformOutObj);
  OutputPayload outPayload = transformOutObj.getOutputPayload();
  ByteArrayOutputStream baos1 = (ByteArrayOutputStream) outPayload.getOutputStream();
  InputStream is1 = new ByteArrayInputStream(baos1.toByteArray());
  //Java Mapping: This funciton code is nothing but your java mapping logic. You can also have INLINE code here
  ByteArrayOutputStream baos2 = YourExtBussLogicMethod(is1);
  // Finally write it to actual mapping runtime outputstream fetched from TransformationOutput
  out.getOutputPayload().getOutputStream().write(baos2.toByteArray())
  /*END ************************************************* PATTERN 2 (GM - JM) **************************************************/
  /*BEGIN ************************************************* PATTERN 3 (JM1 - GM - JM2) **************************************************/
  //Java Mapping1:This funciton code is nothing but your java mapping logic. You can also have INLINE code here
  ByteArrayOutputStream baos = YourExtBussLogicMethod1(is);
  InputStream newInputStream = new ByteArrayInputStream(baos.toByteArray());
  InputPayloadImpl payloadInObj = new InputPayloadImpl(newInputStream);
  TransformationInputImpl transformInObj = new TransformationInputImpl(payloadInObj);
  OutputStream os = new ByteArrayOutputStream();
  OutPayloadImpl payloadOutObj = new OutPayloadImpl(os);
  TransformationOutputImpl transformOutObj = new TransformationOutputImpl(payloadOutObj);
  // Graphical mapping called here, but the transformed stream is written to intermediate ByteArrayOutputStream 'os'
  super.transform(transformInObj, transformOutObj);
  OutputPayload outPayload = transformOutObj.getOutputPayload();
  ByteArrayOutputStream baos1 = (ByteArrayOutputStream) outPayload.getOutputStream();
  InputStream is1 = new ByteArrayInputStream(baos1.toByteArray());
  //Java Mapping2:This funciton code is nothing but your java mapping logic. You can also have INLINE code here
  ByteArrayOutputStream baos2 = YourExtBussLogicMethod2(is1);
  //Finally write it to actual mapping runtime outputstream 'out' fetched from TransformationOutput
  out.getOutputPayload().getOutputStream().write(baos2.toByteArray());
  /*END ************************************************* PATTERN 3 (JM1 - GM - JM2) **************************************************/
  }
  catch (Exception e){
  throw new StreamTransformationException(e.getMessage());
  }
}
class InputPayloadImpl extends InputPayload{
  InputStream in;
    public InputPayloadImpl(InputStream in){
  this.in = in;
  }
  @Override
    public InputStream getInputStream(){
  return in;
  }
}
class TransformationInputImpl extends TransformationInput{
  InputPayload payload;
  public DynamicConfiguration getDynamicConfiguration(){
  return dynamicConfiguration;
  }
  public TransformationInputImpl(InputPayload payload){
  this.payload = payload;
  }
  @Override
  public InputAttachments getInputAttachments(){
  return inputAttachments;
  }
  @Override
  public InputHeader getInputHeader(){
  return inputHeader;
  }
  @Override
  public InputParameters getInputParameters(){
  return inputParameters;
  }
  @Override
  public InputPayload getInputPayload(){
  return payload;
  }
}
class OutPayloadImpl extends OutputPayload {
    OutputStream ou;
    public OutPayloadImpl(OutputStream ou){
  this.ou = ou;}
  @Override
    public OutputStream getOutputStream(){
  return ou;}
}
class TransformationOutputImpl extends TransformationOutput {
    OutputPayload payload;
    public TransformationOutputImpl(OutputPayload payload){
  this.payload = payload;
  }
  @Override
    public void copyInputAttachments(){ }
  @Override
    public OutputAttachments getOutputAttachments(){
  return outputAttachments;
  }
  @Override
    public OutputHeader getOutputHeader(){
  return outputHeader;
  }
  @Override
    public OutputParameters getOutputParameters() {
  return outputParameters;
  }
  @Override
    public OutputPayload getOutputPayload(){
  return payload;
  }
}








The advantage of isolating and developing public ByteArrayOutputStream YourExtBussLogicMethod(InputStream is) java code classes externally is that we don’t have to rely on SAP’s java mapping api to compile the code 🙂

Hope this concept will be helpful. And please share your valuable feedback..

To report this post you need to login first.

10 Comments

You must be Logged on to comment or reply to a post.

  1. Iñaki Vila

    Hi Praveen,

    It’s really amazing, i didn’t know Sunil Chandra‘s blog and i have never thought to call a graphical message mapping inside a java mapping or java ESR mapping. I think with your patterns the java loading in runtime will be faster than the two or three mappings in the operation mapping, also to have the java source available and to avoid the mapping api and the tedious searching of the correct API jar.

    May be, the only problem that i see is to have the runtime processing steps “hidden” in a java code but in my opinion the PI developers need not to fear the Java developing.

    Thanks for your valuable contribution.

    Regards.

    (0) 
    1. Praveen Gujjeti Post author

      Thanks Iñaki Vila for your opinion.

      >>May be, the only problem that i see is to have the runtime processing steps “hidden” in a java code but in my opinion the PI developers need not to fear the Java developing.

      I hope we can use getTrace().addInfo(“xx”)  and Audit.addAuditLogEntry() methods where necessary in the code to understand processing steps 🙂

      Best Regards,

      Praveen Gujjeti

      (0) 
  2. Sunil Chandra

    What a coincidence, I was thinking to blog about the same sometimes back, but the busy schedule kept me in waiting mode. And finally it’s here by Praveen Gujjeti.

    The blog well articulates the idea of merging GM and JM. Apart from runtime performance, it is also a tradeoff between clarity and conciseness.

    Keep experimenting, Keep blogging!

    Regards,

    Sunil Chandra

    (0) 
  3. ambuj mishra

    Nice concept Praveen!

    FYI.. your first pattern implicitly executed in PI.

    As I mentioned in my doc, http://scn.sap.com/docs/DOC-53784

    ESR_JM.png

    Also I think in 2nd and 3rd pattern, GM will be called again after JM execution, but it won’t affect anything as you called it already in JM. right?

    Kudos to your thinking by the way.. great job.

    (0) 
  4. Eng Swee Yeoh

    This super.transform() method came in really handy in one of my recent developments. I had to process the fault response from a web service, and it could be either an application fault response with XML content or a system fault with HTML content.

    Initially, I thought I’ll have a two step mapping, first Java mapping to put everything nicely into XML, then followed by a graphical mapping. Unfortunately, for fault mappings, the Operation Mapping only allows a single mapping step! 🙁 I still wanted to keep my graphical mapping, so I tried this technique – execute the graphical mapping if it’s XML content, otherwise process with Java mapping. It worked perfectly 🙂

    One weird thing though, if I do this via NWDS, the editor complains that the super.transform() method is undefined.

    /wp-content/uploads/2015/01/super_624209.png

    Doing it via the Swing client seems fine. Any idea why?

    Rgds

    Eng Swee

    (0) 

Leave a Reply