Using PI 7.3’s Directory API
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
- 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.)
- Before the import, verify the connection settings are correct:
- Create a Java project in NWDS:
- In NWDS menu: File –> New –> Project
- Select: Java Project
- Enter a project name (In this example, the project name is “Demo_DirAPI”.)
- Import the Service Interface from the ESR:
- Right-click on the project name
- Select: Import…
- Select: Web services –> WSDL and click Next
- Select option: Enterprise Service Repository and click Next
- Enter logon information
- Select the Service Interface in the ESR
- Navigate to; SAP BASIS 7.30 –> http://sap.com/xi/BASIS –> Folders –> Itegration Directory API
- Select the API by going to the appropriate folder and select the service interface:
- You should see the WSDL imported under your project:
- Generate the proxy from the imported WSDL
- Write the code
- Create a new package by right-click on: src, and select: New –> Package
- Enter package name
- Create a new class by right-click on the package and selct: New –> Class
- Enter class name
- 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.
- The result: Done – number of configurations = 27
- Create a new package by right-click on: src, and select: New –> Package
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
@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
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.
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.
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.
There will be additional Directory API enhancements in PI 7.31 SP6, which is scheduled for beginning of Q1/2013.
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
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
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
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.
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
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.
Hi Michal,
I just used wsnavigator to query communication channels and got 266 back.
Default system configuration.
Regards,
William Li
Hi Guys,
thank you both for your help 🙂
what it turned out - we had exactly 200 channels 🙂
Regards,
Michal Krawczyk
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
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
Hi Yashu,
Can you provide more information on what you are trying to create? Give as much details as possible.
Regards,
William Li
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.
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
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
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;
}
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
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.
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
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
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
Hello Vyas,
We are also getting exact same error for all the adapters .
No transport protocol with name "File" and version "" exists for "Adapter Metadata File | http://sap.com/xi/XI/System (SAP BASIS 7.40)"
Any help will be appreciated.
Thanks,
Sateesh Adma
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
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
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
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;
}
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
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);
}
}
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:
javax.xml.ws.BindingProvider;
org.apache.poi.xssf.usermodel.XSSFSheet;
org.apache.poi.xssf.usermodel.XSSFWorkbook;
com.sap.xi.basis.CommunicationChannelID;
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;
com.sap.xi.basis.CommunicationChannelIn;
com.sap.xi.basis.CommunicationChannelInService;
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;
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;
org.apache.poi.ss.usermodel.Cell;
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
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;
}
Hi William Li,
Above code works brilliantly.Could you please share code snippet for communication channel change/create as well .
Thanks
Regards
Venkat
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.
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
Venkat. Your email shows as private.
Sorry,I made it public now
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.
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
Hello Venkat,
Can you please share the code, we are trying to change connection parameters.
Thanks,
Sateesh
Thank you so much William. The above code worked 🙂
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
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
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
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.
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
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
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
Gabriel,
Please use Query of http://Server:port/IntegratedConfigurationInService/IntegratedConfigurationInImplBean?wsdl&mode=ws_policy
For more details, please check these blogs
How to use Integration Directory API
How to consume web services hosted by SAP PI / PO
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
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
Thank you so much Frank.
That worked perfectly... Fantastic stuff
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.
Hello William,
can you say me how I get the ObjectID of the ICO with the Directory API?
Hi All,
I am using directory API to update my REST receiver channel. When I use this from SOAPUI, it works perfectly fine and I am able to change value of any field. However when I try to do the same action using ABAP Program (using Consumer Proxy), I get the following error - 'Enter a value for attribute 'Transport Protocol Version'.
I have not entered any value for this field in SOAP UI and in the ABAP program. I have also validated with Adapter Metadata and the value is blank for this field.
Appreciate if somebody can help me out with this.
Hello Everyone,
I have followed the given steps and tried to execute the given program but It's giving me an error stating "Exception in thread "main" java.lang.NoClassDefFoundError: com/sap/security/hardener/nw/facade/HardenerFacade". I tried to search for possible solution but I am not able to solve this issue. Please help me out with this issue.
Refer the error thread snap attached below.
It'll be really helpful if you provide your expertise to solve this issue.
Thanks