Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
maciej_jarecki
Contributor
0 Kudos

This blog has aim to show how messages can be exchanges between Abap and Java stack in both direction. Typical example of usage is when we need to connect from Java stack to Abap stack to fetch some addition data or to perform additional checks, confirmations etc on Abap stack. On the other hand, lot of functionality of Netweaver has been implemented in Java, that’s why we need sometimes to ask Java stack about something like message processing status or additional information from SLD.

Let’s connect…Java to Abap

This direction of communication offer theoretically lot of ways to connect to Abap. Unfortunately all of them rely on SAP Java Connector. Sap JCO is a middleware component that enable communication between Java and Abap in both directions. There are two version of this component standalone and integrated into SAP J2EE Engine ( implemented as service rfcengine ). In this blog I will use only second one. More sophisticated  solution is to use Sap JRA. Sap Java Resource Adapter is a J2EE compatible connector for SAP system that is based on J2EE Connector Architecture. The J2EE Connector architecture define a standard architecture for communication from existing, heterogeneous Erp systems to any J2EE compatible application server. Additionally SAP JRA implements the standard J2EE interfaces for SAP Java Connector( SAP Jco) so in other words use SAP JCo.

That’s all about definitions, now let see how to use it to establish connection.

Prerequisite

For purpose of this blog Abap remote enable function module has been created ZGETMATDESC with import material number and return their description. Additionally this function module has been exposed as Webservice and there wsdl’s service address is:   http://<server>:<port>/sap/bc/srt/rfc/sap/zabaptojava_ws/011/zabaptojava_ws/zabaptojava_ws

Using Pure JCO

By using word pure I mean that all connection details etc will be provided to java executable entity by user at runtime. So they can be set in program as variable, read from application customizing file or any other source like Webservie or Secure Storage service on AS Java. This type of connection is the simplest one and only require to provide connection details. On the other hand it not require any configuration in Visual Administrator or NWA. Let see sample code

public String JCO(String matnr){

     JCO.Client mConnection;

     JCO.Repository mRepository = null;

try {

   mConnection = JCO.createClient(

                              "XXX", // SAP client

                              "XXX", // userid

                              "XXX", // password

                              "XX", // language

                              "XXX", // application server host name

                              "XX"); // system number

            mConnection.connect();

            mRepository = new JCO.Repository("SAPJCo", mConnection);

            JCO.Function function = null;

            try {

                  function = mRepository.getFunctionTemplate("ZGETMATDESC").getFunction();

                        function.getImportParameterList(). setValue(matnr,"MATERIAL");

                  mConnection.execute(function);

                  JCO.Field returnField = function.getExportParameterList().getField("MATERIALDESC");

                  mConnection.disconnect();

                  return "JCO :" + returnField.getString();

                  }

            catch (Exception ex) {

                  mConnection.disconnect();

                  return "Jco Error : " + ex.getMessage();

                  }

      }

      catch( Exception e){

            return "Global Error : " + e.getMessage();

      }

}

As you can see code is really simple to fetch material description from Ecc.

Connection using Destination Service

This option also involve SAP JCo but also require some configuration in Netweaver. Screenshots are from NWI 7.0 where Visual Administrator is in use, but despite of place of configuration( in 7.1 and above configuration is done in Nwa) nothing has changed. We have two types of destination Http(s) and RFC. There is also Webservice type of destination, but those destination are automatically created when specifying deployable Web service proxies.

To create Destination go to VA->Services->Destinations. In case of RFC type you need to provide detail like in below screen

Now let see program that use this destination

public String Destination_RFC(String matnr) {

try

{

            InitialContext initialcontext = new InitialContext();

            DestinationService dstService = (DestinationService)

            initialcontext.lookup(DestinationService.JNDI_KEY_LOCAL);

            RFCDestination dst = (RFCDestination) dstService.getDestination("RFC", "EHP5MJ");

            java.util.Properties jcoProperties = dst.getJCoProperties();

            JCO.Client mConnection = JCO.createClient(jcoProperties);

                  JCO.Repository mRepository = null; 

            mConnection.connect();

            mRepository = new JCO.Repository("SAPJCORFC", mConnection);

            JCO.Function function = null;

            function = mRepository.getFunctionTemplate("ZGETMATDESC").getFunction();

            function.getImportParameterList(). setValue(matnr,"MATERIAL");

            mConnection.execute(function);

            JCO.Field returnField = function.getExportParameterList().getField("MATERIALDESC");

            return "RFC :" + returnField.getString();

            }

            catch(Exception ex) {

                  return "Rfc Http Error : " + ex.getMessage();

            }

      }

Because used function module has been exposed as webservice, he is accessible with http.

Used Http destination that point to webservice

And code to call Webservice from java.

public String Destination_HTTP(String matnr) {

String tosend = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><SOAP-ENV:Header><sapsess:Session xmlns:sapsess=\"http://www.sap.com/webas/630/soap/features/session/\"><enableSession>true</enableSession></sapsess:Session></SOAP-ENV:Header><SOAP-ENV:Body><ns1:Zabaptojava xmlns:ns1='urn:sap-com:document:sap:soap:functions:mc-style'><IvInput1>" + matnr + "</IvInput1></ns1:Zabaptojava></SOAP-ENV:Body></SOAP-ENV:Envelope>";

HttpURLConnection hurlcon =null;

try{

      InitialContext initialcontext = new InitialContext();

      DestinationService dstService = (DestinationService) initialcontext.lookup(DestinationService.JNDI_KEY_LOCAL);

      Destination destination = dstService.getDestination("HTTP","EHP5MJ_HTTP");

      HTTPDestination httpDestination = (HTTPDestination) destination;

      hurlcon = httpDestination.getURLConnection();

      hurlcon.setRequestMethod("POST");

      hurlcon.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");

      hurlcon.setRequestProperty("Content-Length", "" + Integer.toString(tosend.getBytes().length));

      //Send request

      DataOutputStream wr = new DataOutputStream (hurlcon.getOutputStream ());

      wr.writeBytes(tosend);

      wr.flush ();

      wr.close ();

      hurlcon.connect();

      //Get Response   

      InputStream is = hurlcon.getInputStream();

      BufferedReader rd = new BufferedReader(new InputStreamReader(is));

      String line;

      StringBuffer response = new StringBuffer();

      while((line = rd.readLine()) != null) {

            response.append(line);

            response.append('\r');

      }

      rd.close();

      hurlcon.disconnect();

      return "HTTP : " +response.toString();

      }

      catch(Exception ex)

      {

            return "Http Error : " + ex.getMessage();

      }

One of the biggest advantage is that this solution is fully configurable for each Netweaver environment and that connection details aren’t kept in the program

To configure destination in NW 7.1 and above use quick link: /nwa/destinations.

Using JRA

The last discussed option to connect form Java stack to Abap stack is to use SAP JRA. Contrary to SAP JCo( can be used in each Java based application ), JRA is designed to be used to integrate application based on J2EE because it implements JCA ( J2EE Connector Architecture ). Before we can create connection to Ecc system some configuration steps are necessary. Each SAPJRA instance represents a single SAP system so for each SAP system we need to create new/or clone existing one Resource Adapter. This have to done in Visual Administrator go to Services, Connector Container and check if SAPJRA exist. If no then ask Basis Team to deploy it. From screen below you see what kind of connection details should be set.(they reflect changes in Connection Factory)

“TEST” on the above screen describe Connection Factory that will be used to as parameters provider for connection.

For NW 7.1 log on to  NWA and Configuration Management, Infrastructure, Application Resources.

Code to use JRA

public String JRA(String matnr) {

try

      {

      InitialContext initialcontext = new InitialContext();

      ConnectionFactory connectionfactory =

            (ConnectionFactory)initialcontext.lookup("java:comp/env/TEST");

      Connection connection = connectionfactory.getConnection();        RecordFactory recordFactory = connectionfactory.getRecordFactory();

      MappedRecord input =recordFactory.createMappedRecord("ZGETMATDESC");

      input.put("MATERIAL",matnr);

      Interaction interaction = connection.createInteraction();

      MappedRecord output = (MappedRecord) interaction.execute(null, input);

      String ret = output.get("MATERIALDESC").toString();

  1. connection.close();

      return "JRA : " + ret;       

      }

      catch(Exception e){

            return "Error " + e.getMessage();

      }

Don’t forget to include in ebj.jar file reference to Resource Adapter (In this case Test)

Additionally third method allow calling application to control very important feature which is Transaction. By setting transaction type to “Bean” application can process several calls to an SAP system and make sure that either all calls have been completed or none have been completed.

Let’s connect…Abap to Java

Now connection from Abap to Java. The type that I will discussed is broadly used by SAP to establish the connection to Java stack. You can find it when you configure your Ecc system as local integration engine. To establish connection to SLD and Exchange profile on Ecc you create RFC connection type tcp/ip that point to specific registered program id.  Same approach is used when create Sender RFC commucation channel. Then sender com. channel name is registered as program id.   To create custom solution we need to perform more steps. First is to register program ID. To do that you need to go to Visual Administrator, Service, Jco RFC Provider. As you can see on below screen first section describe where ProgramId will be registered and second section provide information about access to repository of function module( Abap system where called function module has been created, used to import information about parameters etc. )

Report that call simple java function looks like this

CALL FUNCTION 'ZABAPTOJAVA' DESTINATION 'PIMJRFC'
EXPORTING
IV_INPUT1            
= 'hello world'
IMPORTING
EV_OUTPUT1           
= ev_s1
EV_OUTPUT2           
= ev_s2
EXCEPTIONS
system_failure       
= 1
communication_failure
= 2.

As you can see only one difference to typical calling of function module is adding crated tcp/ip type RFC destination to registerd in visual administrator program id. On java side we need to create stateless bean with at least one method processFunction and implements local interfaces. Very important is also to name Bean JNDI same like neme of called on Abap stack function module( in this case ZABAPTOJAVA). Based on this As Java can find which bean should be called.

public void processFunction(com.sap.mw.jco.JCO.Function function) {

            com.sap.mw.jco.JCO.ParameterList input = function.getImportParameterList();

            com.sap.mw.jco.JCO.ParameterList output = function.getExportParameterList();

            com.sap.mw.jco.JCO.ParameterList tables = function.getTableParameterList();

            output.setValue(input.getValue("IV_INPUT1").toString().toUpperCase(), "EV_OUTPUT1");

            output.setValue(new Date().toString(), "EV_OUTPUT2");

      }

Above bean’s code only change input parameter to upper case and return current date from AS Java.

Labels in this area