aspose file tools*
The moose likes Web Services and the fly likes Generating and using client code from wsdl file with wsimport Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Web Services
Bookmark "Generating and using client code from wsdl file with wsimport" Watch "Generating and using client code from wsdl file with wsimport" New topic
Author

Generating and using client code from wsdl file with wsimport

Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Hi,
I'm trying to generate the client code of a web service based on a wsdl file. This web service is used for communicating with IP cameras. The WSDL file is available here:
http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl

My first problem is that wsimport says that the wsdl file does not contain any services. To solve this problem, I've downloaded the wsdl file and added the following lines:

After this wsimport says the following:

So I used -extension and I was able to generate the source files.
Is this okay that I use a "dummy" service location just for generating the source codes?
Is it okay to use the -extension option, or should I define a service differently in the wsdl?

Next problem occurs when I would like to use the generated code. Actually I don't really know how to use it. I have a generated DeviceService class, so I try to instantiate it:

In case I use the wsdl location from the internet, then I get an error that the wsdl does not contain a service definition, so I try to use the modified wsdl file

In that case I receive the following error:

So I'm stuck at this point. Any idea what should I do differently to make this thing work?
I also don't really understand why do I have to specify the wsdl url again, since I generated the code from that wsdl.
Thanks in advance.

Ivan Krizsan
Ranch Hand

Joined: Oct 04, 2006
Posts: 2198
    
    1
Hi!
First of all, without a <service> and <port> element, the WSDL is incomplete. Is this perhaps a WSDL that is imported by another WSDL that in turn specifies the missing elements?
If the WSDL is incomplete, then it is something that should be taken care of by the service provider.
With an incomplete, or invalid, WSDL it becomes much more difficult, if not impossible, to develop a working client for the service.

Second, regarding creating webservice clients, the approach depends a little on the IDE you use:
Here is a tutorial for NetBeans: http://netbeans.org/kb/docs/websvc/client.html
For Eclipse, take a look in section 4.9 in the following e-book (all examples in the book were developed using Eclipse): http://www.slideshare.net/krizsan/scdjws-5-study-notes-3085287
Best wishes!


My free books and tutorials: http://www.slideshare.net/krizsan
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Thanks Ivan. Actually I found the answer for my problem in one of your posts. So the solution is to use the default constructor for the service and change the endpoint

I think the reason why there is no service in the wsdl file because that site does not offer any service. It is a standard for IP cameras, so the cameras itself will offer the service not this site. Is this makes sense?

I've run into another issue unfortunately. I can make calls which requires no authentication, but I don't know how can I insert UsernameToken authentication (what is required here) into the generated classes. Any idea on that issue?
Thanks.
Ivan Krizsan
Ranch Hand

Joined: Oct 04, 2006
Posts: 2198
    
    1
Hi!
I would not aim at modifying the generated classes, but rather modify a local copy of the WSDL by adding the appropriate WS-Policy elements and then generating the client artifacts.
For an example, see this article: http://www.ibm.com/developerworks/java/library/j-jws10/index.html
Best wishes!
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Thanks. I did not want to modify the generated classes, I just thought that maybe it is possible to add the required security part to the messages.
Does this mean that it is not possible to make UsernameToken authentication only with the JDK 1.6 built in capabilities, but I have to use a 3rd party solution for this like the mentioned Metro or Apache Axis2 or ...?
Jason Majchrzak
Greenhorn

Joined: Mar 01, 2012
Posts: 2
Miklos,

I am venturing down the same road that you came from. Can you share your experience? How did you manage to resolve adding the service to the ONVIF WSDL document? Also, were you able to pass user name, password, nonce and request time? I've been able to use wsimport to generate the required classes, but I don't have a "DeviceService.java" file generated even when I've modified a local copy of devicemgmt.wsdl.

Thanks,
Jason
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Hi Jason,
I suspended working on this issue, so I made no further progress regarding this.
Best regards,
Miklós
Jason Majchrzak
Greenhorn

Joined: Mar 01, 2012
Posts: 2
Thank you for an update Miklos!
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
You were so close!
After banging my head with this for a few days I finally found the fix!



/Edit
It works for devices that don't require authentication. I'm still stuck with authenticating when needed.
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
I finally solved it:

Start off by browsing into the Axis camera's web interface:

Open your browser
Open the Axis camera's web interface
Go to Setup -> System Options -> Security -> ONVIF
Add a user!

Now for the code part.
You start off by reading the server's clock:


Then, you create an authentication header.
For that you need to bind a handler:


Implement the handler


And there you have it.
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
An important thing I've discovered about Axis cameras:
Once you set the initial root password using the web interface, the ONVIF interface will not allow access.
You must reset the camera to its factory defaults in order to use the ONVIF interface without credentials.
You should now be able to initialize the root password and ONVIF passwords via the ONVIF interface.
If you did, however initialize the camera's root password via the web interface, you should also manually add an ONVIF user as explained above.
I would like to thank this blessed behavior for wasting my time.
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
Looks like I forgot to add the implementation of the message digest creation:

Sarfraz Ahmed
Greenhorn

Joined: May 30, 2012
Posts: 4
I tried it using C. Because I am writing my API in C. But it can not authenticate me. My question is am I making three parameters right (Random number, Time String and password Digest). I verify my SHA1 Output on this site. http://hash.online-convert.com/sha1-generator

Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
nonce is an array of 16 bytes, not an int.
the byte[16] none may contain zeros, so use memcpy, instead of sprintf
Sarfraz Ahmed
Greenhorn

Joined: May 30, 2012
Posts: 4
I changed my code as follow. But still giving same Error. The returned HTTP Error code is 500. I changed the nonce for every request for testing purposes.

Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
1. Is your clock synchronized with the device you're trying to connect to?

2. I've tried using the nonce you've posted and got the following results:

Input
nonce str: 1234567892133613
time str: 1970-01-11T21:39:42.208Z
pass str: 123456

In bytes:
nonce bytes: [49, 50, 51, 52, 53, 54, 55, 56, 57, 50, 49, 51, 51, 54, 49, 51]
time bytes: [49, 57, 55, 48, 45, 48, 49, 45, 49, 49, 84, 50, 49, 58, 51, 57, 58, 52, 50, 46, 50, 48, 56, 90]
pass bytes: [49, 50, 51, 52, 53, 54]

Result:
digest str: TiWxOU9wmwlMQlIx3a856HpQYAk=
digest bytes: [84, 105, 87, 120, 79, 85, 57, 119, 109, 119, 108, 77, 81, 108, 73, 120, 51, 97, 56, 53, 54, 72, 112, 81, 89, 65, 107, 61]

Please make sure you get the same result when using this exact input.
Sarfraz Ahmed
Greenhorn

Joined: May 30, 2012
Posts: 4
I tried the Inputs and my Outputs Matches with your ones. I am attaching my whole code. May be at some other place I am making mistake. That I am unable to detect.

I create my headers in this function.



and this is how I am sending SOAP request.




Thanks
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
By the username, I'm guessing that you are using an axis camera.
You need to create a user specific for ONVIF in the cameras web interface.

You should also try to read the camera's current time, and use that for authentication instead of your local time.
See my example above
Sarfraz Ahmed
Greenhorn

Joined: May 30, 2012
Posts: 4
Its a canon camera, VB-M40. I tried to read the time value from the camera and then use that string to authenticate. But the Error response was same.
Jane Chu
Greenhorn

Joined: Oct 11, 2012
Posts: 3
Hello,

I am very new on the tech of web services.

Somehow, I got a sample code online which is very similar to the one here. The wsdl and xsd files are downloaded from onvif. The original code works well. (I have got the device info, server time)

Now, I want to make more service requests. For example, getServices. I added the following 2 lines in:

boolean includeCapability = true;
device.getServices(includeCapability);

but, the response link seemed fixed to the one pointing to device info. Here is the error message:

unexpected XML tag. expected: {http://www.onvif.org/ver10/device/wsdl}GetServicesResponse but found: {http://www.onvif.org/ver10/device/wsdl}GetWsdlUrlResponse

Does anyone could help me out? Any help would be highly appreciated.


Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
Yeah, I've cleaned it up and reposted this solution on stack overflow http://stackoverflow.com/questions/8798419/build-soap-web-service-client-using-wsdl-documents-in-eclipse/10394687

It looks that either the device you're communicating with returns the wrong class, or that it tries to return an error.
I'd suggest using wireshark to read the traffic directly and look at the xml that you end up sending and the xml you receive back from the device.
It's usually readable enough to help you understand what went wrong.
Jane Chu
Greenhorn

Joined: Oct 11, 2012
Posts: 3
Yeah, It's you! I tried looking for you for several days! I am glad to meet you here!
Thank you very much for your reply. I will try wireshark. I did exactly as you suggested in the comments right after that "URL url" line. Your comments were pretty straight forward and easy to follow. In this case, do you have any idea where might go wrong? Thank you again!
Jane Chu
Greenhorn

Joined: Oct 11, 2012
Posts: 3
You are right. The traffic I caught by wireshark shows that the device got the request, but the "Connection: close". Then it went to somewhere else. Thank you very much again!
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Thanks to Ivan's and Ido's advices I was able to authenticate the user and execute different calls from the device management service. So thank you very much for that.
I've started to experiment with the Media service but I wasn't able to get it work.
I'm instantiating the service with the following code:

I also instantiate a DeviceService to get the date and time for the authentication. Using that information I create a SecurityHandler and "attach" it to the service according to the previous posts.
This works nicely for the Device calls, but whenever I call media.getProfiles() I receive the following exception:


Using wireshark I can even see the answer was sent by the camera (I've pasted the request and the response at the and of my post).
I tried to google for the exception but I haven't found the solution yet. What can be the problem?

The outgoing message is :


The response is:
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
You might need to find a different version of the wsdl file. You used soap 1.2 and the device requires you to use soap 1.1
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Are you sure? For me it looks like the camera has no problem with this, since it sends the answer. The Java code generates this exception when processing the answer. According to the comment read on the ONVIF forum:
Generally the ONVIF working groups and Technical Committee take utmost care to ensure interoperability within the same version set by the namespace. So you can safely use the latest wsdl files for your implementation. Newer functionality is defined optional and bound to capabilities so that a client can easily find out whether a device supports it.

So based on this I should be able to use the latest wsdls only.

UPDATE:
I've downloaded and used the old WSDL files, but I receive the same error message.
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Further analyzing the problem I found the source of the problem (but I still can't find the solution).

It looks like the camera can send SOAP 1.2 messages, in case if the request is SOAP 1.2(I've used the test tool to check this).
Despite of the fact that the code generates a correct link for the Envelop namespace at the beginning:


It also contains the SOAP 1.1 Envelop namespace URL:

In case I send a message without the second envelop namespace, the camera response in SOAP 1.2 format.

So the problem is reduced back to the following:
Why the generated code do this? How can I convince wsimport to generate the correct Envelop?
I use the -extension with wsimport.>
Ido Shlomo
Greenhorn

Joined: Apr 17, 2012
Posts: 10
I think that the problem is in the fake service we added to the wsdl
It should be soap12:address instead of soap:address
Miklos Szeles
Ranch Hand

Joined: Oct 21, 2008
Posts: 142
Unfortunately that did not help.
I don't know what would be the "correct" solution - I hope somebody will answer it in the future - but I found a workaround which works:
After generating the source files, I've replaced all
http://schemas.xmlsoap.org/soap/envelope
with
http://www.w3.org/2003/05/soap-envelope

That solves the issue.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Generating and using client code from wsdl file with wsimport
 
Similar Threads
WSDL to service
wsdl2java stubs naming problem
Axis2 - WSDL to code
The AXIS engine could not find a target service to invoke
Problem with Java Client