cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
19222
Views
53
Helpful
65
Replies

How-To: Using a custom Java class in UCCX 5.x (SOAP Example)

Anthony Holloway
Cisco Employee
Cisco Employee

Update: Due to the loss of dropbox, the links to dropbox offline project are no longer active.  Please use this awesome document as your new reference:

https://supportforums.cisco.com/document/97736/uccx-8x-really-simple-soap-client-no-custom-jar

 

Update:  Due to a server failure, the links to http://www.avholloway.com/ are no longer active.  Please download the offline project.

 

This tutorial can be viewed in its entirety on my web site:

 

http://www.avholloway.com/vtools/ipcc/custom-java/soap/

 

The first thing we need to do is find out what version of Java is our server running, this way we know which version of Java to compile in.

 

This document outlines the JRE (Java Runtime Environment) version compatibility with all versions of CRS:

"Cisco Customer Response Solutions (CRS) Software and Hardware Compatibility Guide" - June 16, 2008

http://www.cisco.com/en/US/docs/voice_ip_comm/cust_contact/contact_center/crs/express_compatibility/matrix/crscomtx.pdf

 

According to that document, my version of CRS, v5.0(1) SR2, uses JRE 1.5.0.  So I will go to Sun's site and download the JDK (Java Development Kit) for that version.

 

Alternatively, you could determine the Java version right on the CRS server itself.  Though, there could be multiple JRE's installed, and the CRS Engine uses only the one listed in the above document.

 

Sun's page for previous JDK versions:

http://java.sun.com/javase/downloads/previous.jsp

 

I would typically install the JDK and JRE for 1.5.0 on my personal computer and not on the server.  This way I can do all of my Java testing offline, making sure it all works, before even uploading it to the server.  I did one additional, and optional, thing to make developing easier.  I added the bin directory to my path variable so I can execute the necessary Java commands from any directory.  This is outlined in the installation instructions, which can be found on the JDK download page.

 

So now we have our development environment setup.  Yep, all we needed was the JDK, and the JRE, the only other tool we'll use it already on every system; a text editor.  I will use TextEdit on my Mac for this example, but you could easily use Notepad on Windows, or nano on Linux.

 

I will not get into the details of writing Java apps/classes, so for the purpose of this tutorial I will offer my simple SOAP class to you.

 

Disclaimer: I am not a Java programmer.  In fact, this is my very first program in Java, and I learned just enough for this task.

 

Browseable link: http://www.avholloway.com/vtools/ipcc/custom-java/soap/SimpleSOAP.java.txt

Download link: http://www.avholloway.com/vtools/ipcc/custom-java/soap/SimpleSOAP.java

 

Now, we need to compile our source code into byte code so the JRE can execute it.  Compiling the .java file will result in a new file of the same name, but with the .class extension on it.

 

http://www.avholloway.com/vtools/ipcc/custom-java/soap/compiling-SimpleSOAP.png - Command Prompt>javac SimpleSOAP.java

 

Now we need to test this new class to see if it works before we add the complexity of the CRS environment.

 

Let's create another Java file, and this one will utilize our newly created class.

 

Browseable link: http://www.avholloway.com/vtools/ipcc/custom-java/soap/RunMyCode.java.txt

Download link: http://www.avholloway.com/vtools/ipcc/custom-java/soap/RunMyCode.java

 

Now we compile that source code so it can also be ran.

 

http://www.avholloway.com/vtools/ipcc/custom-java/soap/compiling-RunMyCode.png - Command Prompt>javac RunMyCode.java

 

Next we pass the RunMyCode class to the JRE like so (Note the absence of the .class or .java file extension):

 

http://www.avholloway.com/vtools/ipcc/custom-java/soap/running-RunMyCode.png - Command Prompt>java RunMyCode

 

Your output should look something similar to this:

 

Screen shot: http://www.avholloway.com/vtools/ipcc/custom-java/soap/running-RunMycode.png

Browseable link: http://www.avholloway.com/vtools/ipcc/custom-java/soap/soap-response.xml

 

OK, so if everything is working up to this point, it's safe to assume that our CRS server will be able to utilize our class as well.

65 Replies 65

andywallace
Level 1
Level 1

Thanks for you work on this. It has help me out and i did manage to get your script up and running.

I am now a little stuck on mine and wonder id anyone can help. I have the basic JAVA runing from an ivr script it goes off and fetches a sesion ID for me. THis bit works. However i am having problme parsing the XML to get the bit of data i want.

THe response from the get xml document is attaqched. I need to be able to create an xml path to get the EstablishSessionResult in to a varible.

Using yours as an examplre to amend mine i always get an error. it says illegalaxis name: descendent;nested exception.

Any idea if it is possible and how do i create the XML path. I am very new to JAVA in fact 1 weeks experence so i am a little stuck now.

Any help would be much appreciated.

Andy

I downloaded your file, and put it through my XML XPath Visualizer tool.  Several things it didn't like:

1.  Get rid of the \r\n in the file.  These are escaped carriage return / line feed indicators.  XPath doesn't know what to do with it.

2.  Get rid of all the backwards slashes you have in there "\".  You have a bunch of these in the first few lines.

Once you get rid of the above, XPath can query for the value in the file as:

/descendant::EstablishSessionResponse/child::EstablishSessionResult

I didn't try running this through UCCX. Historically, it has had issues with custom namespaces, but this should get you pointed in the right direction.

Cliff

Please rate helpful posts

Thanks Cliff, i will let you know how i get on.

Andy

i.chichikov
Level 1
Level 1

Hi All!

I try create a script with custom Java class by this manual. And have a problem:

I uploaded successfully  SimpleSOAP.jar  to Custom File (Classes) Configuration, add it to "Selected Classpath Entries", restart CCX Engine and CCX Administration.

Open Script Editor and trying create new Variable, but there is no SimpleSOAP type.

Where is my fault?

Hi

It's not a fault - at least, it's not your fault!

When I've done this it doesn't appear in the variable pane until you first instantiate an instance of the new object - this seems to bring it 'into memory'.

I do this by doing something simple like:

- add a 'do' step

- in the box, enter:

{

SimpleSOAP x = new SimpleSOAP();

}

If you hit apply, and it doesn't error out, then you should see the new class in the variable pane from then on.

If it errors, try it with a built in var type to check your syntax:

{

String x = new String();

}

If that fails consider:

- does your class need parameters in the constructor call?

- if you have put the class in a package (as any IDE will encourage you to), then it must be fully qualified...e.g:

{

com.mystuff.SimpleSOAP x = new com.mystuff.SimpleSOAP();

}

Also you may not need a variable assigning. For example, you might do something like this, where retVal is a String var:

{

SimpleSOAP x = new SimpleSOAP();

SimpleSOAP.doSomethingUseful("username", "password");

retVal = SimpleSOAP.getResult();

}


Regards

Aaron Harrison

Principal Engineer at Logicalis UK

Please rate helpful posts...

Aaron Please remember to rate helpful posts to identify useful responses, and mark 'Answered' if appropriate!

Thanks for the very clear and concise instructions.


Valber Carvalho
Level 1
Level 1

Hi Anthony,

How are you? I hope you are ok.

I am testing in LAB some possibilites to connect the UCCX8.0 on the Web Services. I tested your Java class and it is working very well. Congratulations!!!

I had to modify somethings and now when I use the Netbeans,  I can see the HTTP Response normally.

Nowadays, I am working with

  • CCX Editor 8.0,
  • IPIVR Version 8.0.2.10000-42,
  • Demo License with 25 ports.

See my SOAP request:

http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

 

    http://tempuri.org/">

      1111111111

      1111

   

 

See the result:

http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">http://tempuri.org/">*****Cosan***********V*****

I would like to create a script that could send this SOAP Request, and it could receive the SOAP Response, but every script that I try to create I don't have any sucess.

I am checking some HTTP components, and I realize that I have one choice in these HTTP Components. Is it right? Could the demo license give me other choices?

Do you have any example for UCCX8.0?

Thanks a lot.

Valber.

Valber,

I created a document for that, available at

https://supportforums.cisco.com/docs/DOC-23899

G.

Hi Gergely,

I have read your new document and I saw the SimpleSOAP.java created by Clifford MCGlamry available in this post and both of them are very clear. Based in your experiences I made a Script.aef that is working perfectly. I would like to share it with the community.

I am grateful for your help.

Thank you,

Valber

Hi Valber,

I ran through your script quickly. To be quite honest with you, there are two things I need to warn you about. I mean, your script looks fine and it's waaaaay simpler than mine, but I see two places where simplicity may hurt.

1. crafting XML using strings - it works, it's fine, but it's not elegant at all. I have no particular strong argument against it, but somehow I've got the feeling that String + String + String = XML just does not look right.

2. using subString and/or subSequence - again, it works, it's fine, but again, not elegant at all. Pretend, something changes on the SOAP server side, they might start sending a new element or a comment or anything, and the subString method will not match, or would send you unexpected information, or just fail (if you try to match beyond the string's length).

What I would recommend you to consider:

RE 1: create an XML file with tokens like this #foo##bar#. Save this XML on the UCCX (as a document). In your script, grab it using a Create XML Document step. Then do a keyword transform step, replacing the tokens with real values, like #foo# = ABCD and #bar# = XYZ. And then send the transformed document to the SOAP server.

RE 2: use the Get XML data = XPath may seem a bit complicated, but I promise, you'll be able to learn it.

Good luck.

G.

Hi Gergely,

I totally agree with you and I am trying to improve it, now. 

I am testing your suggestions, and now I know how to read, to get and to chance values of a standard XML, but I can't get any attribute when I have a Soap Request XML. They are differents, and I think that I have some problem to use the XPath to this kind of format (FormatSOAPRequest.txt - attahched).

I am seeing in w3schools, but they talking about Standard XML.

Do you have some example to get attributes from SoapRequest.xml?

Could you help me, please?

Could you test my app, please?

I am sending a simple app to read both of formats. You can use it. Please, create a folder called xml in Document Management. After that , upload these files txt into it.

Thank you very much,

Valber.

Hi Valber,

there's no such thing as a 'Standard XML' and a 'Soap Request XML' - they are both XML files. I mean, they're either regular XML files, or they are not, but then they are not XML files at all.

I know those nasty little namespaces mess things up a bit, but hey, SOAP is not meant to be easy (this is why I try to exchange data with JSON whenever it's possible).

I did some modifications in your script and it works great with the 'FormatSOAPRequest.txt" file as well.

Actually, two things:

1. when creating an XML document using the Create XML Document from a document which is already in the UCCX repository, you don't have to use the Create File Docuemnt step at all. You can use the Create XML Document step right away, like this:

doc = Create XML Document (DOC[FormatSOAPRequest.txt])

2. if there are namespaces involved, they are kind of references to something external - an as such, their URI should be used. Yet there's one way: fly through all nodes, at any depth (do //*) and use a filter with the handy local-name() function. Like this:

firstResponse = Get XML Document Data (doc, "//*[local-name()='Brand']")

secondResponse = Get XML Document Data (doc, "//*[local-name()='Result']")

Screenshot:

G.

Hi Gergely,

Thanks for your help. I finished the Sript Application, and it is working very well. At end, it is simple to be understood.

I would like to share it with the community.

Thank you very much,

Valber.

Hi Valber,

your script looks OK, there are some points I am not quite comfortable with - but, again, if it works, then it's alright.

G.

Dear All,

I had created custome Java Class to use SOAP Requests using IVR. My code is working fine when I call it from main function, but when I call the function from IVR Script at UCCX 8.5.1 I get following error:

system.io.IOException: Server returned HTTP response code 500 for url

I had successfully tested my code from below machines/OS:

Windows XP, Windows7, RedHat Linux, Solaris

Please tell me that what could be the problem.

Below is the code:

    public String[] BalanceInquiry( String sAccountNumber ) {

        String sReturnVal[] = new String[4];

        String soapResponse    =    "";

        String soapRequestURL    =     "http://10.0.18.24/PhoenixWebService/Service1.asmx";

        String soapRequestTXT    =     "\n" +

                        "http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +

                        "    \n" +

                        "        http://tempuri.org/\">" +

                        "              " + sAccountNumber + "" +

                          "              " +

                        "    \n" +

                        "";

        try {

            URL url = new URL(soapRequestURL);

            URLConnection conn = url.openConnection();

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

            conn.setRequestProperty("Content-Length", "" + soapRequestTXT.length());

            conn.setDoOutput(true);

            OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());

            wr.write(soapRequestTXT);

            wr.flush();

            BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            String line = "";

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

                soapResponse += line;

            }

            wr.close();

            rd.close();

            //if the everything went ok

            if(readStatusResponseXML(soapResponse) == true)

            {

                //set status value

                sReturnVal[0] = "true";

                //get balance

                sReturnVal[1] = readBalanceResponseXML(soapResponse);

                //get complete response

                sReturnVal[2] = soapResponse;

                //Get Responce Statuas

                sReturnVal[3] = readResponceValXML(soapResponse);//@Kashif

            }

            //else log the error here

            else

            {

                //set status value

                sReturnVal[0] = "false";

                sReturnVal[1] = "";

                sReturnVal[2] = soapResponse;

                //Get Responce Status

                sReturnVal[3] = readResponceValXML(soapResponse);//@Kashif

                //TODO

                //write logging code here

            }

            return sReturnVal;

        } catch (Exception exception) {

            sReturnVal[0] = exception.getMessage();

            return sReturnVal;

        }

    }