Skip to Content

Using PI 7.3’s Directory API

Directory API has been used by many companies to streamline processes and ease situations where manual configuration of Integration Directory objects is not the ideal solution, such as the updating of the communication channels after transport.  If a program can carry out this task, then it can minimize mistakes, speed up deployment and increase security.

Directory API has gone through different iterations, due to added functionalities and new objects introduced in newer releases.  The older version (XI 3.0, PI 7.0x, PI 7.1x) of the API can no longer be used with the newer versions of PI.  As the result, the development of the API has also changed.

The previous version of the API can be referenced in: Directory API Development

In this blog, I will introduce the basic development of using the PI 7.3x Directory API.  The example can be used as a template  to start a Directory API project, and hopefully overcome some of the initial hurdles.

Scenario:

The sample scenario is simply to get the number of Integrated Configuration objects, which was introduced in PI 7.1.

Pre-requisite:

The following roles must be added to the username executing the API:

  • SAP_XI_API_DISPLAY_J2EE
  • SAP_XI_API_DEVELOP_J2EE

Step-by-Step Guide

  1. Import the WSDL of the Directory API from the Enterprise Service Repository (ESR)

    The ESR contains the Service Interface of the API and using NWDS, we can import the WSDL of the service interface directly from the ESR.  (The NWDS version should at least match the PI versoin.)

    1. Before the import, verify the connection settings are correct:
      1. In NWDS’s main menu, go to Windows –> Preferences
        /wp-content/uploads/2012/10/pic1_146074.png
      2. In Preferences:  go to Web Services –> Enterprise Service Browser
        /wp-content/uploads/2012/10/pic2_146081.png
      3. Enter the appropriate server information
        /wp-content/uploads/2012/10/pic3_146082.png
    2. Create a Java project in NWDS:
      1. In NWDS menu:  File –> New –> Project
      2. Select: Java Project
      3. Enter a project name (In this example, the project name is “Demo_DirAPI”.)
    3. Import the Service Interface from the ESR:
      1. Right-click on the project name
      2. Select:  Import…
        /wp-content/uploads/2012/10/pic4_146083.png
      3. Select: Web services –> WSDL and click Next
        /wp-content/uploads/2012/10/pic5_146087.png
      4. Select option: Enterprise Service Repository and click Next
        /wp-content/uploads/2012/10/pic6_146088.png
      5. Enter logon information
        /wp-content/uploads/2012/10/pic7_146089.png
      6. Select the Service Interface in the ESR
        1. Navigate to; SAP BASIS 7.30 –> http://sap.com/xi/BASIS –> Folders –> Itegration Directory API
        2. Select the API by going to the appropriate folder and select the service interface:
          /wp-content/uploads/2012/10/pic8_146093.png
      7. You should see the WSDL imported under your project:
        /wp-content/uploads/2012/10/pic9_146094.png
  2. Generate the proxy from the imported WSDL
    1. Right-click on the WSDL and navigate to Web Serivices –> Generate Client:
      /wp-content/uploads/2012/10/pic10_146095.png
    2. Move the selector to “Develop client” and click Finish
      /wp-content/uploads/2012/10/pic11_146096.png
      If prompted, click on the default, “Update WSDL”:
      /wp-content/uploads/2012/10/pic12_146097.png
    3. You should see new packages generated:
      /wp-content/uploads/2012/10/pic13_146098.png
  3. Write the code
    1. Create a new package by right-click on: src, and select: New –> Package
      /wp-content/uploads/2012/10/pic14_146099.png
    2. Enter package name
      /wp-content/uploads/2012/10/pic15_146100.png
    3. Create a new class by right-click on the package and selct: New –> Class /wp-content/uploads/2012/10/pic16_146101.png
    4. Enter class name
      /wp-content/uploads/2012/10/pic17_146102.png
    5. Copy-n-paste the sample code:
      
      package com.demo.dirapi;
      
      import java.util.List;
      
      import javax.xml.ws.BindingProvider;
      
      import com.sap.xi.basis.IntegratedConfigurationIn;
      import com.sap.xi.basis.IntegratedConfigurationInService;
      import com.sap.xi.basis.IntegratedConfigurationQueryIn;
      import com.sap.xi.basis.IntegratedConfigurationQueryOut;
      import com.sap.xi.basis.MessageHeaderID;
      
      public class IntegratedConfiguration {
           private static String apiURL = "/IntegratedConfigurationInService/IntegratedConfigurationInImplBean?wsdl=binding&mode=ws_policy";
           private String serverPort = "usphlvm1426:50000";
           private String user = "demo";
           private String password = "abcd1234";
           private String url = new String();
           private IntegratedConfigurationIn port;
      
           public IntegratedConfiguration() {
                setURL(serverPort);
                try {
                     port = getPort();
                }
                catch (Exception e) {
                     e.printStackTrace();
                }
           }
      
           public List query() {
                IntegratedConfigurationQueryIn queryIn = new IntegratedConfigurationQueryIn();
                MessageHeaderID msgHdr = new MessageHeaderID();
                queryIn.setIntegratedConfigurationID(msgHdr);
                IntegratedConfigurationQueryOut queryOut = port.query(queryIn);
                List lMsgHdr = queryOut.getIntegratedConfigurationID();
                return lMsgHdr;
           }
      
           private void setURL(String serverPort) {
                if (serverPort == null)
                     return;
                else
                     this.url = this.url.concat("http://").concat(serverPort).concat(apiURL);
           }
      
           private IntegratedConfigurationIn getPort() throws Exception{
                IntegratedConfigurationIn port = null;
                try {
                     IntegratedConfigurationInService service = null;
      
                     service = new IntegratedConfigurationInService();
      
                     port = (IntegratedConfigurationIn) service.getIntegratedConfigurationIn_Port();
                    BindingProvider bp = (BindingProvider)port;
                    bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, user);
                    bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
                    if (url.length() != 0)
                         bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
                }
                catch (Exception ex){
                     ex.printStackTrace();
                }
                return port;
           }
      
           /**
            * @param args
            */
           public static void main(String[] args) {
                // TODO Auto-generated method stub
                IntegratedConfiguration test = new IntegratedConfiguration();
                List listMsgHdr = test.query();
                System.out.println("Done - number of configurations = " + listMsgHdr.size());
           }
      
      }
      

      Note:  The apiURL value can be obtained by going the the WSNavigator.

    6. The result:  Done – number of configurations = 27
To report this post you need to login first.

57 Comments

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

  1. Larry Martin

    I followed the instructions and can run the code successfully from my local pc. I had been getting the wsdl in a different way and it was creating file names that were too long but your procedure fixed it.

    However, when I try to run in PI I get the following error which I believe is caused by the fact that the tmpUrl object is null.

    Caused by: java.lang.NullPointerException: while trying to invoke the method java.net.URL.getProtocol() of an object loaded from local variable ‘tmpUrl’

    at com.sap.xi.basis.IntegratedConfigurationInService.<clinit>(IntegratedConfigurationInService.java:14)

    I am creating what appears to be a valid url for our system…see below…but it is not used because the static constructor is failing and I would only set the url after creating the port

    Here is the url:

    http://pollux.conocophillips.net:57100/IntegratedConfigurationInService/IntegratedConfigurationInImplBean?wsdl=binding&mode=ws_policy

    (0) 
    1. Dennis Root

      @Larry Martin:

      Did you find a solution for you problem? I am running into the same error. On the local pc everything is working, but when I deploy the program as a web service (servlet) and a development component in combination with an enterprise application it leads to your mentioned error. It seems that the variable “port” is not filled/initialized.

      Thank you,

      Dennis

      (0) 
  2. Jonathan Barrington

    Thanks for the update William. The new API is much better. I’ve written a number of wrappers around it and hopefully someday it is cleaned up and robust enough to share.

    Hopefully PI 7.31 features get added to the Directory API too.

    -Manager Alert Rules (not just consumers)

    -Managing Alert Rules and Value Mapping in the Config Scenerios **

    Not specific to 7.31, but I’d also love to see a WhereUsedList service.

    **On that note, hopefully both of these object types get an ‘Assign to Config Scenario’ and ‘Remove from Config Scenrio’ option in the normal ID as well.

    (0) 
    1. Jonathan Barrington

      I’d like to add a caution that since the ConfigScenarioIn service does not support Value Mapping groups or Alert Rules, when using that service to change an existing config scenario, any Alert Rules and Value Mappings for it will be lost.

      Unfortunately it meant wasted effort for me as I had spent a good amount of time assigning Value Mapping Groups to Config Scenarios.

      Hopefully this is fixed in the next version.

      (0) 
  3. Jonathan Barrington

    We have also found that the Directory API does not support the Advanced Settings in Integrated Configurations for scenario-specific Staging and Logging.

    But even worse, is that when you update/change an Integrated Scenario using Directory API, if it had scenario-specific settings, they will be lost. This is dangerous as certain combinations of staging for EOIO messages can cause messages to get stuck.

    It seems there has not been much attention given to Directory API in the EHP1 update, leading to these gaps and issues, which frankly make it dangerous to use. Hopefully SAP plans to patch these gaps and hopefully avoid them again in the future.

    (0) 
  4. Erik Roskothen

    Hi William,

    I’m trying to create a proxy for that API on ABAP side. But there is no service interface to be seen in ESR for any of the API Objects according to your topic f above.

    Do you know how to manage this?

    Thank you,

    Erik

    (0) 
  5. Michal Krawczyk

    hi Bill,

    with read operation the results are limited to 200 only

    is there a way to configure that somehow ? 🙂

    Thank you for any tips 🙂

    Regards,

    Michal Krawczyk

    (0) 
    1. William Li Post author

      Hi Michal,

      I am not aware of a configuration parameter.  I don’t have a PI system with more than 200 ICOs to test this out 🙁

      If I need to retrieve the info for all the ICOs, I normally use the QUERY operation to retrieve all instances of the ICOs (sender/receiver component/interface/namespace).  Then, I use the READ operation to retrieve the details each ones based on the QUERY results.

      Are you saying the QUERY operation is limited to 200?

      If it is the READ operation with the 200 limit, then maybe you can group only 200 for each READ at a time.

      If it is the QUERY operation with the 200 limit, then you can use a filter, e.g. = “A*” and go through the alphabet (it’s case-sensitive, so you may have to go through the alphabet twice).

      Regards,

      William Li

      (0) 
  6. Larry Martin

    I also do not have a PI system with more than 200 ICO’s…yet. However, we use many of the other Directory API’s and have never run into any sort of limit on the number of objects returned by the Query operation. We have more than 200 Configuration Scenarios, Communication Channels and Interface Determinations and have never seen a limit.

    (0) 
    1. Michal Krawczyk

      hi Larry,

      I even see this in wsnavigator when I run a query for all communication channels – only 200 is returned, do you have more over there when you search for all ?

      Thank you,

      Regards,

      Michal Krawczyk

      (0) 
      1. Larry Martin

        Michal. We are not running our query in WSNavigator. We have written java classes that wrap each of the Directory API objects, such as Communication Channel, so we are running the query from our own java class and when we do that we do not see any limit.

        It would seem like the limit is in WSNavigator not in the actual API…which is actually a Web Service call.

        I have not used WSNavigator for this for a long time but I would bet there is some sort of configuration paramter that is limiting the number of responses. In fact, I am not aware of a way to limit the number fo objects returned from a Query call but I have not looked for one either so there could be an optional parameter.

        (0) 
      2. William Li Post author

        Hi Michal,

        I just used wsnavigator to query communication channels and got 266 back.

        CommChan.png

        Default system configuration.

        Regards,

        William Li

        (0) 
  7. Yashu Vyas

    Hi Bill,

    I’m following your earlier blogs on communication channel creation and trying to create SOAP receiver communication channel using Java-only PI 7.31 directory APIs. I have passed all the required parameters to the CommunicationChannelIn service, but it’s throwing error – “Enter at least one object key for operation ‘create'”.

    When I tried to test the service through WS Navigator, it’s giving exception – “Enter a value for attribute ‘Transport Protocol Version'” which doesn’t exists in case of SOAP adapter creation. I also tried with other communication channels but no luck so far.

    Can you please suggest me any work around or point out where I might me going wrong.

    Your expert advice and help will be highly appreciated.

    Regards,

    Yashu Vyas

    (0) 
    1. William Li Post author

      Hi,

      When running into such issues, one method I always use when creating an object is to look at an existing object and their values for the different fields.  You can use the “read” operation in WSNavigator to examine an existing receiver communication channel to determine the values you should use.

      Regards,

      William

      (0) 
      1. William Li Post author

        Hi Yashu,

        Can you provide more information on what you are trying to create?  Give as much details as possible.

        Regards,

        William Li

        (0) 
        1. Yashu Vyas

          Hi Bill,

          Thanks for all the support and help offered.

          We are facing following problems while trying to create communication channel through Dir API –


          In PI 7.0 Dir API’s we had the following constructor –

          CommunicationChannelCreateChangeIn crtChan = new CommunicationChannelCreateChangeIn();


          and used the function ‘crtChan.setCommunicationChannel(chans)’ to associate the object ‘chans’ of type CommunicationChannelRestricted with ‘crtChan’, and created the communication channel using the below code –

          ConfigurationObjectModifyOut resp = port.create(crtChan);


          As we don’t have any corresponding function in PI 7.31 Dir API’s, we are not sure how to set the object of type RestrictedCommunicationChannelType on the object of class CommunicationChannelCreateChangeInType.


          We want to associate RestrictedCommunicationChannelType object with CommunicationChannelCreateChangeInType object to invoke the ‘create’ function of the class CommunicationChannelIn.


          Below is how we are trying to create the Communication Channel:


          CommunicationChannelIn port = (CommunicationChannelIn) service.getCommunicationChannelIn_Port();


          ConfigurationObjectModifyOutType resp = port.create(crtChan);


          We are getting the error ‘Enter at least one object key for operation ‘create”. We assume that it is because there is no ‘set’ method in the class CommunicationChannelCreateChangeInType

          to associate RestrictedCommunicationChannelType with it,

          Any help and pointers will be highly appreciated.

          Regards,

          Yashu

          Note : I’m trying to retrofit the java code mentioned in your earlier blog on communication channel creation.

          (0) 
          1. William Li Post author

            Hi Yashu,

            Please don’t provide me with the code, I will not be able to debug it for you.  Instead, I will use WSNavigator to create the comm chan.  If WSNavigator works, then I can use it to write the code.

            Please let me know the details of the comm chan you want to create.

            Regards,

            William

            (0) 
            1. Yashu Vyas

              Hi Bill,

              We are trying to create a SOAP receiver communication channel through PI 7.31 Dir API. Please help us with that.

              Thanks a lot for your valuable time and help.

              Thanks & Regards,

              Yashu Vyas

              (0) 
          2. Larry Martin

            Here is code to create a restricted CC from a noram CC.

            public RestrictedCommunicationChannel duplicateChannel(CommunicationChannel currentChannel) throws Exception {

              RestrictedCommunicationChannel newChannel = new RestrictedCommunicationChannel();

              newChannel.setCommunicationChannelID(currentChannel.getCommunicationChannelID());

              newChannel.setMasterLanguage(currentChannel.getMasterLanguage());

              ObjectAdministrativeData currentAdministrativeData = currentChannel.getAdministrativeData();

              if (currentAdministrativeData != null) {

               RestrictedObjectAdministrativeData newAdministrativeData = new RestrictedObjectAdministrativeData();

               newAdministrativeData.setResponsibleUserAccountID(currentAdministrativeData.getResponsibleUserAccountID());

               newAdministrativeData.setFolderPathID(currentAdministrativeData.getFolderPathID());

               newChannel.setAdministrativeData(newAdministrativeData);

              }

              List <LONGDescription> descriptions = currentChannel.getDescription();

              if ((descriptions != null) && (descriptions.size() > 0))

               for (int index = 0; index < descriptions.size(); index++)

                newChannel.getDescription().add(descriptions.get(index));

              newChannel.setAdapterMetadata(currentChannel.getAdapterMetadata());

              newChannel.setDirection(currentChannel.getDirection());

              newChannel.setTransportProtocol(currentChannel.getTransportProtocol());

              newChannel.setTransportProtocolVersion(currentChannel.getTransportProtocolVersion());

              newChannel.setMessageProtocol(currentChannel.getMessageProtocol());

              newChannel.setMessageProtocolVersion(currentChannel.getMessageProtocolVersion());

              newChannel.setAdapterEngineName(currentChannel.getAdapterEngineName());

              List <GenericProperty> genericProperties = currentChannel.getAdapterSpecificAttribute();

              if ((genericProperties != null) && (genericProperties.size() > 0))

               for (int index = 0; index < genericProperties.size(); index++)

                newChannel.getAdapterSpecificAttribute().add(genericProperties.get(index));

              List <GenericPropertyTable> adapterSpecificTableAttributes = currentChannel.getAdapterSpecificTableAttribute();

              if ((adapterSpecificTableAttributes != null) && (adapterSpecificTableAttributes.size() > 0))

               for (int index = 0; index < adapterSpecificTableAttributes.size(); index++)

                newChannel.getAdapterSpecificTableAttribute().add(adapterSpecificTableAttributes.get(index));

              newChannel.setModuleProcess(currentChannel.getModuleProcess());

              newChannel.setSenderIdentifier(currentChannel.getSenderIdentifier());

              newChannel.setReceiverIdentifier(currentChannel.getReceiverIdentifier());

              return newChannel;

            }


            (0) 
            1. Yashu Vyas

              Hi Larry,

              It seems your utility is for duplicating an existing channel of type CommunicationChannel to create the CC of type RestrictedCommunicationChannel. However my requiement is to create the very first CC in the system using PI 7.31 API’s.


              Our program doesn’t have any information about any existing channel and as mentioned in my earlier query to Bill we are trying to associate RestrictedCommunicationChannelTypeobject with CommunicationChannelCreateChangeInType object to invoke the ‘create’ function of the classCommunicationChannelIn.


              Regards,

              Yashu Vyas

              (0) 
              1. Larry Martin

                Vyas. We do not have anything to create a CC. Our code starts with the CC’s we already have, lists them and updates them when requested.

                (0) 
        2. William Li Post author

          Hi Yashu,

          I was able to create a receiver SOAP comm chan using WSNavigator.  The exported XML is below:  (you can copy it to a file)

          <CommunicationChannelCreateRequest>

            <CommunicationChannel>

              <MasterLanguage>EN</MasterLanguage>

              <CommunicationChannelID>

                <PartyID></PartyID>

                <ComponentID>BC1</ComponentID>

                <ChannelID>R_soap_test</ChannelID>

              </CommunicationChannelID>

              <AdapterMetadata>

                <Name>SOAP</Name>

                <Namespace>http://sap.com/xi/XI/System</Namespace>

                <SoftwareComponentVersionID>7e9a3ca7-82ab-11df-b3ad-f6750a424100</SoftwareComponentVersionID>

              </AdapterMetadata>

              <Direction>Receiver</Direction>

              <TransportProtocol>HTTP</TransportProtocol>

              <TransportProtocolVersion></TransportProtocolVersion>

              <MessageProtocol>SOAP</MessageProtocol>

              <MessageProtocolVersion></MessageProtocolVersion>

              <AdapterSpecificAttribute>

                <Name>XMBWS.TargetURL</Name>

                <Value>http://wsf.cdyne.com/WeatherWS/Weather.asmx</Value>

              </AdapterSpecificAttribute>

              <AdapterSpecificAttribute>

                <Name>XMBWS.ProxyHost</Name>

                <Value>proxy</Value>

              </AdapterSpecificAttribute>

              <AdapterSpecificAttribute>

                <Name>XMBWS.ProxyPort</Name>

                <Value>8080</Value>

              </AdapterSpecificAttribute>

              <AdapterSpecificAttribute>

                <Name>XMBWS.DefaultSOAPAction</Name>

                <Value>http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP</Value>

              </AdapterSpecificAttribute>

              <AdapterSpecificAttribute>

                <Name>useProxy</Name>

                <Value>1</Value>

              </AdapterSpecificAttribute>

            </CommunicationChannel>

          </CommunicationChannelCreateRequest>

          You can change the <ComponentID> to one that is available on your PI system and import the XML into WSNavigator to test.

          If it is successful, then these are the basic parameters to use.  If you need other attribute, e.g. proxy user and password, then you can use a READ operation to determine the names to use.

          Regards,

          William

          (0) 
          1. Yashu Vyas

            Hi Bill,

            As suggested earlier we used READ operation and make it work to create CC through WSNavigator. However when we tried to do the same through our Java code using PI 7.31 DIr API it fails to create the same. That was the primary intent I wanted to share the code snippet with you as are not able to associate RestrictedCommunicationChannelType object with CommunicationChannelCreateChangeInType object to invoke the ‘create’ function of the class CommunicationChannelIn.

            We are getting the error ‘Enter at least one object key for operation ‘create”. We assume that it is because there is no ‘set’ method in the class CommunicationChannelCreateChangeInType to associate RestrictedCommunicationChannelType with it.

            It’ll be great if you can throw some light on this aspect.

            Thanks & Regards,

            Yashu Vyas

            (0) 
          2. Yashu Vyas

            Hi Bill,

            We fixed the issue and were able to create the communication channel through PI 7.31 Dir API utility.

            Thanks a lot for all your help and suggestions.

            Regards,

            Yashu Vyas

            (0) 
  8. Vicky G

    Hi Bill,

    I have created a dirapi utility to make mass changes to pi communication channels (only) in PI 7.11 environment and it works great 🙂

    Now do I need to write the whole code again to be able to use this utility on PI 7.31?

    Vicky

    (0) 
    1. William Li Post author

      Hi Vicky,

      You may not need to.  There are 2 sets of APIs in PI 7.31, one is for PI 7.11 and before.  The other is for PI 7.11 and after.  With PI 7.11, there were many enhancements in the ESR and ID, the older version can only handle those interfaces and configurations using the “classical” way, while the newer version can handle all.  Communication channels happens to be unchanged between the versions….I think.  So, you should be able to work with communication channels using both APIs.

      If you need to go to the new API, then you will need to re-write.

      Regards,

      William

      (0) 
  9. Soundarya Kavuri

    Hi William,

    I have implemented the above code and was sucessfully able to retrieve the Number of ICO’s and Number of Communication Channels . But my requiremnt is to get the Communication Channel names along with the Attributes. Could you please suggest as to what parameters should be used to get the Communication Channel names and List of attributes used in the Channel like user name , password etc instead of just getting the number , i need to get the names of the Channels as well.

    Thanks,

    Soundarya

    (0) 
    1. Larry Martin

      The way to get the detail information on each object is to iterate througth the list of object, such as Commununications Channels and call the method to get the individual channel. Here is my overloaded method. I am using a log4j logger and have a standard method to log and check the returned message collection…which I will share if you need it.

      public CommunicationChannel returnChannel(String partyId, String componentId, String channelId) throws Exception {
        return returnChannel(partyId, componentId, channelId, Utility.MESSAGE_SEVERITY_ERROR);
      }

      public CommunicationChannel returnChannel(String partyId, String componentId, String channelId, String exceptionSeverity) throws Exception {
        CommunicationChannelID communicationChannelID = new CommunicationChannelID();
        if ((partyId != null) && (partyId.length() > 0)) communicationChannelID.setPartyID(partyId);
        if ((componentId != null) && (componentId.length() > 0)) communicationChannelID.setComponentID(componentId);
        communicationChannelID.setChannelID(channelId);
        return returnChannel(communicationChannelID);
      }

      public CommunicationChannel returnChannel(CommunicationChannelID communicationChannelID) throws Exception {
        return returnChannel(communicationChannelID, Utility.MESSAGE_SEVERITY_ERROR);
      }

      public CommunicationChannel returnChannel(CommunicationChannelID communicationChannelID, String exceptionSeverity) throws Exception {
        CommunicationChannel returnValue = null;
        try {
         CommunicationChannelReadIn returnChannelIn = new CommunicationChannelReadIn();
         returnChannelIn.getCommunicationChannelID().add(communicationChannelID);
         returnChannelIn.setReadContext(ReadContextCode.ACTIVE);
         Logger.getRootLogger().setLevel(Level.OFF);
         CommunicationChannelReadOut returnChannelOut = port.read(returnChannelIn);
         Logger.getRootLogger().setLevel(defaultLevel);
         LogMessageCollection messageCollection = returnChannelOut.getLogMessageCollection();
         integrationUtility.handleLogMessages(CLASS_NAME + ” – Return Channel (” + communicationChannelID.getComponentID() + “/” +
           communicationChannelID.getChannelID() + “)”, messageCollection, exceptionSeverity);
         try {
          returnValue = returnChannelOut.getCommunicationChannel().get(0);
         } catch (NullPointerException eNull) {
          logging.writeMessage(“Returned Communication Channel is null for (” + communicationChannelID.getComponentID() + “/” +
            communicationChannelID.getChannelID() + “)”, GLBLLogging.MSG_TYPE_DEBUG);
         }
         catch (IndexOutOfBoundsException eIndex) {
          logging.writeMessage(“Returned Communication Channel Array had zero objects (” +
            communicationChannelID.getChannelID() + “/” + communicationChannelID.getComponentID() + “)”,
            GLBLLogging.MSG_TYPE_DEBUG);
         }
        } catch (Exception e) {
         Logger.getRootLogger().setLevel(defaultLevel);
         String errorMessage = “PI Integration ” + CLASS_NAME + ” Return Channel failed = ” + e.getMessage();
         logging.writeError(errorMessage, e);
         integrationUtility.sendNotification(Utility.ERROR_STATUS, “PI Integration ” + CLASS_NAME + ” Return Channel error”, errorMessage);
         throw e;
        }
        return returnValue;
      }


      (0) 
  10. Soundarya Kavuri

    Hi Martin,

    I tried using the above code you suggested but The Utility parameters in the above code are not identified in my editor and hence it shows error at those lines. I am looking for some code to read the channel names , its attributes etc using DIR API . Could you suggest any sample code to do so similar to the one suggested by William in this blog to get the number of ICO’s. I am looking for such code to read the Channel name instead of the number of channels. I just wanted to understand the metod to be used to  get the channel name . Is it CommunicationChannelreadIn. If yes, what are the input parameters to it?

    Appreciate any quick responses.

    Thanks,

    Soundarya

    (0) 
    1. Larry Martin

      The Utility class is my own, along with a few others. Here is my code for listing out all of the fields in a Communication Channel. In some places a subroutine is called but you will be able to see all of the fields.

      The way to determine what to do for any one type of object is to loook in the classes that were generated when you processed the WSDL file. They list all of the fields. Granted you have to sometimes go down a few levels to get to the things you can log but everything is there.

      public void logChannel(CommunicationChannel currentChannel) throws Exception {

        SimpleDateFormat dateFormat = new SimpleDateFormat(“dd MMM yyyy @ HH:mm:ss”);

        CommunicationChannelID currentID = currentChannel.getCommunicationChannelID();

        logging.writeMessage(“Communication Channel (” + currentID.getComponentID() + “/” +

          currentID.getChannelID() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        logging.writeMessage(”   Master Language (” + currentChannel.getMasterLanguage() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        ObjectAdministrativeData administrativeData = currentChannel.getAdministrativeData();

        if (administrativeData != null) {

         logging.writeMessage(”   Administrative Data – Responsible User Account ID (” +

           administrativeData.getResponsibleUserAccountID() +

           “) Folder Path ID (” + administrativeData.getFolderPathID() +

           “) Last Change User Account ID (” + administrativeData.getLastChangeUserAccountID() +

           “) Last Change Date Time (” +

           dateFormat.format(administrativeData.getLastChangeDateTime().toGregorianCalendar().getTime()) +

           “)”, GLBLLogging.MSG_TYPE_DEBUG);

        }

        List <LONGDescription> descriptions = currentChannel.getDescription();

        integrationUtility.logDescription(descriptions);

        logging.writeMessage(”   Communication Channel ID – Party ID (” + currentID.getPartyID() + “) Component ID (” +

          currentID.getComponentID() + “) Channel ID (” + currentID.getChannelID() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        DesignObjectID adapterMetadata = currentChannel.getAdapterMetadata();

        if (adapterMetadata != null) {

         logging.writeMessage(”   Adapter Metadata – Name (” + adapterMetadata.getName() + “) Namespace (” +

           adapterMetadata.getNamespace() + “) Software Component Version ID (” +

           adapterMetadata.getSoftwareComponentVersionID() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        }

        logging.writeMessage(”   Direction (” + currentChannel.getDirection() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        logging.writeMessage(”   Transport Protocol (” + currentChannel.getTransportProtocol() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        logging.writeMessage(”   Transport Protocol Version (” + currentChannel.getTransportProtocolVersion() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        logging.writeMessage(”   Message Protocol (” + currentChannel.getMessageProtocol() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        logging.writeMessage(”   Message Protocol Version (” + currentChannel.getMessageProtocolVersion() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        logging.writeMessage(”   Adapter Engine Name (” + currentChannel.getAdapterEngineName() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        List <GenericProperty> genericProperties = currentChannel.getAdapterSpecificAttribute();

        integrationUtility.logGenericProperty(”   “, “Adapter Specific Attribute”, genericProperties);

        List <GenericPropertyTable> adapterSpecificTableAttributes = currentChannel.getAdapterSpecificTableAttribute();

        integrationUtility.logGenericPropertyTable(”   “, “Adapter Specific Table Attribute”, adapterSpecificTableAttributes);

        ModuleProcess moduleProcess = currentChannel.getModuleProcess();

        boolean moduleProcessHeader = false;

        if (moduleProcess != null) {

         List <ProcessStep> processSteps = moduleProcess.getProcessStep();

         if ((processSteps != null) && (processSteps.size() > 0)) for (int index = 0; index < processSteps.size(); index++) {

          if (moduleProcessHeader == false) {

           moduleProcessHeader = true;

           logging.writeMessage(”   ModuleProcess”, GLBLLogging.MSG_TYPE_DEBUG);

          }

          ProcessStep processStep = processSteps.get(index);

          logging.writeMessage(”      Process Step – Module Name (” + processStep.getModuleName() + “) Module Type (” +

            processStep.getModuleType() + “) Parameter Group ID (” + processStep.getParameterGroupID() +

            “)”, GLBLLogging.MSG_TYPE_DEBUG);

         }

         List <ParameterGroup> parameterGroups = moduleProcess.getParameterGroup();

         if ((parameterGroups != null) && (parameterGroups.size() > 0)) for (int index = 0; index < parameterGroups.size(); index++) {

          if (moduleProcessHeader == false) {

           moduleProcessHeader = true;

           logging.writeMessage(”   ModuleProcess”, GLBLLogging.MSG_TYPE_DEBUG);

          }

          ParameterGroup parameterGroup = parameterGroups.get(index);

          logging.writeMessage(”      Parameter Group – Parameter Group ID (” + parameterGroup.getParameterGroupID() + “)”,

            GLBLLogging.MSG_TYPE_DEBUG);

          List <RestrictedGenericProperty> parameters = parameterGroup.getParameter();

          if ((parameters != null) && (parameters.size() > 0)) for (int index1 = 0; index1 < parameters.size(); index1++) {

           RestrictedGenericProperty parameter = parameters.get(index1);

           logging.writeMessage(”         Parameter – Name (” + parameter.getName() + “) Value (” +

             parameter.getValue() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

          }

         }

        }

        ChannelAdditionalIdentifier senderIdentifier = currentChannel.getSenderIdentifier();

        if (senderIdentifier != null) {

         logging.writeMessage(”   Sender Identifier – Scheme ID (” + senderIdentifier.getSchemeID() + “) Scheme Agency ID (” +

           senderIdentifier.getSchemeAgencyID() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        }

        ChannelAdditionalIdentifier receiverIdentifier = currentChannel.getReceiverIdentifier();

        if (receiverIdentifier != null) {

         logging.writeMessage(”   Receiver Identifier – Scheme ID (” + receiverIdentifier.getSchemeID() + “) Scheme Agency ID (” +

           receiverIdentifier.getSchemeAgencyID() + “)”, GLBLLogging.MSG_TYPE_DEBUG);

        }

      }

      (0) 
  11. Soundarya Kavuri

    Hi Martin,

    I am presently running the above code in NWDS in my system. It would be great if you could give the entire logic along with the utility class as i’m unable to connect to some of the term used in the above code while using in my nwds editor.

    As of now , the code that i’m using to get the communication channel number is as follows:

    1. import
      javax.xml.ws.BindingProvider;

    1. import
      org.apache.poi.xssf.usermodel.XSSFSheet;
    2. import
      org.apache.poi.xssf.usermodel.XSSFWorkbook;

    1. import
      com.sap.xi.basis.CommunicationChannelID;
    2. import
      com.sap.xi.basis.CommunicationChannelQueryIn;

    import com.sap.xi.basis.IntegratedConfigurationIn;

    import com.sap.xi.basis.IntegratedConfigurationInService;

    import com.sap.xi.basis.IntegratedConfigurationQueryIn;

    import com.sap.xi.basis.IntegratedConfigurationQueryOut;

    1. import
      com.sap.xi.basis.CommunicationChannelIn;
    2. import
      com.sap.xi.basis.CommunicationChannelInService;
    3. import
      com.sap.xi.basis.CommunicationChannelQueryOut;

    import com.sap.xi.basis.MessageHeaderID;

    import com.sap.xi.basis.global.LONGDescription;

    import java.io.File;

    import java.io.FileNotFoundException;

    1. import
      java.io.FileOutputStream;

    import java.io.IOException;

    import java.util.Date;

    import java.util.Map;

    import java.util.Set;

    import java.util.TreeMap;

    import org.apache.poi.hssf.usermodel.HSSFCell;

    import org.apache.poi.hssf.usermodel.HSSFCellStyle;

    import org.apache.poi.hssf.usermodel.HSSFDataFormat;

    import org.apache.poi.hssf.usermodel.HSSFRow;

    import org.apache.poi.hssf.usermodel.HSSFSheet;

    import org.apache.poi.hssf.usermodel.HSSFWorkbook;

    import org.apache.poi.hssf.util.HSSFColor;

    1. import
      org.apache.poi.ss.usermodel.Cell;
    2. import
      org.apache.poi.ss.usermodel.Row;

    import org.apache.poi.xssf.usermodel.XSSFSheet;

    import org.apache.poi.xssf.usermodel.XSSFWorkbook;

    public class
    CommunicationChannels {

         private static String apiURL = “/CommunicationChannelInService/CommunicationChannelInImplBean?wsdl=binding&mode=ws_policy”;

         private String serverPort = “”;

         private String user = “”;

         private String password = “”;

         private String url = new String();

         private
    CommunicationChannelIn
    port;

         public
    CommunicationChannels() {

            
    setURL(
    serverPort);

             try {

                  port = getPort();

            
    }

             catch (Exception e) {

                 
    e.printStackTrace();

            
    }

         }

         public List
    query() {

            
    CommunicationChannelQueryIn queryIn =
    new CommunicationChannelQueryIn();

            
    CommunicationChannelID msgHdr =
    new
    CommunicationChannelID();    

              queryIn.setCommunicationChannelID(msgHdr);

            
    CommunicationChannelQueryOut queryOut =
    port.query(queryIn);

            
    List lMsgHdr = queryOut.getCommunicationChannelID();

             return lMsgHdr;

            

         }

         private void setURL(String
    serverPort) {

             if (serverPort == null)

                  return;

             else

                  this.url = this.url.concat(http://).concat(serverPort).concat(apiURL);

         }

         private
    CommunicationChannelIn getPort()
    throws Exception{

            
    CommunicationChannelIn port =
    null;

             try {

                 
    CommunicationChannelInService service =
    null;

                 
    service =
    new CommunicationChannelInService();

                 
    port = (CommunicationChannelIn) service.getCommunicationChannelIn_Port();

                
    BindingProvider bp = (BindingProvider)port;

                
    bp.getRequestContext().put(BindingProvider.
    USERNAME_PROPERTY, user);

                
    bp.getRequestContext().put(BindingProvider.
    PASSWORD_PROPERTY, password);

                 if (url.length() != 0)

                     
    bp.getRequestContext().put(BindingProvider.
    ENDPOINT_ADDRESS_PROPERTY, url);

            
    }

             catch (Exception ex){

                 
    ex.printStackTrace();

            
    }

             return port;

         }

         /**

          * @param args

          */

         public static void main(String[]
    args) {

             //TODO
    Auto-generated method stub

            
    CommunicationChannels test =
    new CommunicationChannels();

            
    List listMsgHdr = test.query();

            
    System.
    out.println(“Done – number of communication channels = “ +
    listMsgHdr.size());

           //Blank
    workbook

            
    XSSFWorkbook workbook =
    new XSSFWorkbook();

              //Create a
    blank sheet

            
    XSSFSheet sheet = workbook.createSheet(
    “Communication Channel ID’s”);

             //This
    data needs to be written (Object[])

            
    Map<String, Object[]> data =
    new TreeMap<String, Object[]>();

            
    data.put(
    “1”, new Object[] {“S.no”, “Comm
    Channel”
    , “Number”});

            
    data.put(
    “2”, new Object[] {1, “number
    of Comm channels”
    ,+ listMsgHdr.size() });

           //Iterate
    over data and write to sheet

            
    Set<String> keyset = data.keySet();

             int rownum = 0;

             for (String key :
    keyset)

            
    {

            
    Row row = sheet.createRow(rownum++);

            
    Object [] objArr = data.get(key);

             int cellnum = 0;

             for (Object obj :
    objArr)

            
    {

            
    Cell cell = row.createCell(cellnum++);

             if(obj instanceof String)

            
    cell.setCellValue((String)obj);

             else if(obj instanceof Integer)

            
    cell.setCellValue((Integer)obj);

            
    }

            
    }

             try

        
        {

             //Write
    the workbook in file system

            
    FileOutputStream out =
    new FileOutputStream(new File(“C:/Java/CommchannelList.xlsx”));

            
    workbook.write(out);

            
    out.close();

            
    System.
    out.println(“Comm List written successfully on disk.”);

            
    }

              catch (Exception e)

              {

            
    e.printStackTrace();

            
    }

         }

    }

    With the help of the above code i’m able to successfully populate an xls sheet with the number of Comm Channels but unable to read the Comm channel names and attributes.

    Could you please help me out as to at which place , the above method that you mentioned should be called? My requiremnt is to populate the xls with comm channel names and attributes.

    Could you please give methe end to end code along with the utility class that you are using as the above code that you mentioned has references to you own classes which i’m unaware of.How should this metho be called from the main method? The current channel is one of the parameters in this method, from where should this be passed?

    Aprreciate your response and looking forward for any quick help on the same.

    Regards,

    Soundarya

    (0) 
    1. William Li Post author

      Okay, here is the snippet of code to get the list of all comm chans and details.  You use query to get the list, then use read to retrieve the detailed info for each.

      public void getCommChanList() {

        CommunicationChannelQueryIn queryIn = new CommunicationChannelQueryIn();

        CommunicationChannelID id = new CommunicationChannelID();

        queryIn.setCommunicationChannelID(id);

        try {

         CommunicationChannelIn port = getPort();

         CommunicationChannelQueryOut queryOut = port.query(queryIn);

         List<CommunicationChannelID> ids = queryOut.getCommunicationChannelID();

         System.out.println(ids.size());

         for (int i=0; i<ids.size(); i++) {

          CommunicationChannel cc = read(ids.get(i), port);

          CommunicationChannelID ccid = cc.getCommunicationChannelID();

          String party = ccid.getPartyID();

          String component = ccid.getComponentID();

          String channel = ccid.getChannelID();

          String transport = cc.getTransportProtocol();

          String msgProtocol = cc.getMessageProtocol();

          DesignObjectID metadata = cc.getAdapterMetadata();

          String adapter = metadata.getName();

          System.out.println(“\t” + i + “: ” + party +”/” + component + “/” + channel + “\t” + adapter + “|” + transport + “|” + msgProtocol);

         }

        }

        catch (Exception e) {

        

        } 

      }

      public CommunicationChannel read(CommunicationChannelID id, CommunicationChannelIn port) {

        CommunicationChannel cc = null;

        CommunicationChannelReadIn readIn = new CommunicationChannelReadIn();

        ReadContextCode code = ReadContextCode.ACTIVE;

        readIn.setReadContext(code);

        readIn.getCommunicationChannelID().add(id);

       

        CommunicationChannelReadOut readOut = port.read(readIn);

        List<CommunicationChannel> ccList = readOut.getCommunicationChannel();

        for (int i=0; i<ccList.size(); i++) {

         cc = ccList.get(i);

        }

        return cc;

      }

      (0) 
        1. Larry Martin

          Venkat. I do not have create code but I do have c ode that will modify a Communication Channel. You have to create a Restricted one first and then modify the fields in the restricted object. We have some code that updates the password and it has some general methods. It is really too big to post here but I can email it.

          The code uses our own logging object and a few other things but you will be able to see how the restricted object is built, modified and saved in the directory.

          (0) 
          1. Venkat Nimmagadda

            Thanks Larry Martin.

            You can find my mail id  here .Please share that piece of code.

            >>You have to create a Restricted one first and then modify the fields in the restricted object.

            Are you going to create new channel with the existing channel details and then modify it  or just modify the existing channel and activate it ?

            Thanks

            Regards

            Venkat

            (0) 
          2. Srikanth Mavuri

            Hi Lary,

            I am also working on direcotry API, looking for the same code snippet for midifying the existing communication channels…. Could you please share that piece of code to me. so that i can try that one.

            Thanks in Advance.

            Regards,

            Srikanth Mavuri.

            (0) 
            1. Venkat Nimmagadda

              Hi Srikanth,

              As per SCN policies ,we shouldn’t share our mail id or contact details here .We should make it public in our profile itself if you want to share it to others as I did above.

              Regards

              Venkat

              (0) 
  12. Soundarya Kavuri

    Hi William,

    I have a question regarding the apiURL “CommunicationChannelInService/CommunicationChannelInImplBean?wsdl=binding&mode=ws_policy” restrcited to the PI version of the system. For eg. if i intend to use the above code for PI 7.11 Version , the same code which worked for 7.3 is not working for 7.1. Could you please tell me if it is a different aproach to be followed for 7.11 System? Except for the server port , all other details should be the same rite?

    But my code is not working for 7.11. When i run it in NWDS , it starts and says terminated without any errors. What could be the reason?

    Thanks,

    Soundarya

    (0) 
    1. William Li Post author

      Hi,

      The same steps should also work for 7.11, but will not work for 7.1.  7.1 has a different set of Directory API.

      Regards,

      William

      (0) 
  13. Soundarya Kavuri

    Ok. Thank you.

    I am trying to use the API for Configuration Scenario objects to print the objects in the Configuration scenario using NWDS.I tried using CongigurationScenarioqueryIn but I’m stuck as to what parameters are to be used to fetch the objects.Is it possible to provide the sample code for this scenario. I need the sample code to fetch the Configuration Scenario objects like Configuration Scenario name Sender system , receiver sytem , sender and reciever communication channels , Receiver determination etc… Which method is to be used to fetch all these objects of a Configuration Scenario. It would be of great help if youc an provide me the sample code to fetch the same.

    Thanks,

    Soundarya

    (0) 
  14. Larry Martin

    Soundarya. The way to find out how to get all of the fields and their detail content so you can list or display them is to look in the com.sap.xi.basis directory for the appropriate object, ConfigurationScenario, in this case. Many of the components are other types you need to look up to see their specific detail fields.

    Using this process you can get any of the component objects you need.

    (0) 
  15. Dennis Root

    Hi William,

    First of all thank you for your great directory API Tutorials!

    Now to my problem:

    I followed your tutorial from above and the local client is working just fine!

    Now I tried to deploy this example as a Web Service (combination of EAR and DirectoryServletTool) on our Netweaver Application Server. I am using NWDS and one Software Component containing two Development Components.

    The error “JAX-WS deployable proxy is instantiated with ‘new’ instead of been injected. Cannot find WSDL URL for service [class com.sap.xi.basis.IntegratedConfigurationInService]” occures in the method “getPort”.

    Can you give me a hint on how to resolve this issue?

    Thank you in advance!

    Regards,

    Dennis

    (0) 
    1. Shiladitya Sarkar

      Hi Dennis,

      Did you manage to get a solution for your problem. I’m trying to use the DirAPI from within a receiver java proxy and receiving the exact same error as described by you.

      Regards,

      Shiladitya

      (0) 
  16. Gabriel Sagaya Paneer Selvam

    Hi William,

    I am trying to extract the entire Integrated Configuration object (ICO) names from Integration Directory API instead of total count of ICO objects. Could you please help me on that.

    Regards

    Gabriel

    (0) 
      1. Tiago Soares

        Hi Ragbu.

        Is it possible to get, the object ID associated with a given Integrated Configuration via this service?

        I’m trying to get WSDL of a given ICO and only way that I can think of is via object ID. Is there any other way?

        Thanks

        (0) 
        1. Frank Adams

          Hi,

          first of all: no, you cannot retrieve an ICO’s object ID by using Directory API.

          But you can get the ICO WSDL by specifying the full ICO key, e.g.

          http://<your host>:<your_http_port>/dir/wsdl?ot=ic&senderParty=<ICO sender party>&senderService=<ICO sender service>&receiverParty=<ICO virtual receiver party>&receiverService=<ICO virtual receiver service>&interface=<ICO sender interface name>&interfaceNamespace=<ICO sender interface namespace>

          Please also check the various examples in http://<your host>:<your_http_port>/dir/wsdl.

          Further notes:

          – Just use empty string for empty key fields, e.g. for empty sender party: …. /dir/wsdl?ot=ic&senderParty=&senderService=<ICO sender service>&…..

          You do not need to URL encode the namespace parameter, but it will also work with the encoded value

          Best regards,

          Frank

          (0) 
          1. Larry Martin

            You can get the list of ICO’s using the most recent version of the Directory API’s. We have an interface that is doing it every day in both single stack and dual stack. We are no 7.4 in both environments.

            (0) 

Leave a Reply