Showing posts with label eclipse. Show all posts
Showing posts with label eclipse. Show all posts

Friday, November 14, 2008

JAX-RPC Client in Netbeans 6.5RC2 vs Eclipse Ganymede

I'm not certain, but I think there's something goofy with the JAX-RPC client support in Netbeans 6.5 RC2 using the JAX-RPC Web Services plugin version 0.2.

I'm attempting to interface with a Liferay 5.1.2 instance so that I can add and modify users from an external application. Nothing too difficult. After installing the JAX-RPC plugin in Netbeans, I chose New->Web Service Client and pointed the dialog to the WSDL URL that Liferay provides. For example: http://10129:password@liferayserver:8080/tunnel-web/secure/axis/Portal_UserService?wsdl . Note that I'm passing a Liferay user-id and password and specifying /secure/ in the URI. This Liferay user-id happens to correspond to an administrator in my portal instance. While it is possible to get the WSDL without going through authentication (just omit /secure/ and don't pass credentials), I wanted to give Netbeans all the hints I could to make this easy on myself.

At this point Netbeans went about creating a massive number of files to consume the service. Seriously, a boatload. Once the client was created I tried testing the service using the functionality in Web Service References, but kept getting deserialization errors about an "invalid boolean value". No matter which function I tried to call I got the same error. Interestingly enough, by making a few intentional mistakes and watching the Liferay logs I could see the actual calls were making it to the server just fine, and I guess that makes sense since the errors are during deserialization of the returned data.

I tried sticking a client invokation on a JSP in my project by right-clicking in the open JSP file and choosing Web Service Client Resources->Call Web Service Operation. Specifically, I'm trying for getUserById(LiferayID) from which I should receive a Liferay User object, and from that I'm going to display the user's email address on my page.

No luck. Same damn deserialization error, this time reported in the Glassfish V2 output. It looks something like this:

java.rmi.RemoteException: Runtime exception; nested exception is:
deserialization error: invalid boolean value:
at com.sun.xml.rpc.client.StreamingSender._handleRuntimeExceptionInSend(StreamingSender.java:348)
at com.sun.xml.rpc.client.StreamingSender._send(StreamingSender.java:330)
at com.sgmbiotech.liferay.client.UserServiceSoap_Stub.getUserById(UserServiceSoap_Stub.java:1432)
...
Caused by: deserialization error: invalid boolean value:
at com.sun.xml.rpc.encoding.SOAPDeserializationContext.deserializeMultiRefObjects(SOAPDeserializationContext.java:107)
at com.sun.xml.rpc.client.StreamingSender._send(StreamingSender.java:256)
... 35 more

Awesome. I stepped through the code with the debugger and while I can see the exception occuring, I don't really understand why it's occuring. I did some searching online and couldn't find much except some complaining about Netbeans JAX-RPC support in general.

On a hunch that the problem was with Netbeans' code generation, I decided to fire up Eclipse (Ganymede, full EE install) and use it to generate the appropriate classes. I created a new web project and then did a New->Other->Web Services->Web Service Client, turned the slider down to "assemble client", and pointed the service definition at the Liferay WSDL file. Note: I recommend copy / pasting the URL to the WSDL file into the service definition field in this dialog, because using Browse and typing it in is an experience much like falling off a moving truck into a giant pile of cheese graters. I won't go into it.

Eclipse generated the client for me which consisted of only six class files, unlike the 312 that Netbeans produced. It even used good package names. I believe it Eclipse in this case is just calling out to WSDL2Java from the Axis project, because I've done it by hand once or twice and got very similar results if memory serves me.

I manually imported the Eclipse-generated client into my Netbeans project, added some necessary jar files, hand-wrote the call in my jsp file and voila - IT WORKED.

The invocation code in the JSP file looked like this:

com.liferay.portal.service.http.UserServiceSoapProxy proxy = new com.liferay.portal.service.http.UserServiceSoapProxy();
((javax.xml.rpc.Stub)proxy.getUserServiceSoap())._setProperty(javax.xml.rpc.Stub.USERNAME_PROPERTY, "10129");
((javax.xml.rpc.Stub)proxy.getUserServiceSoap())._setProperty(javax.xml.rpc.Stub.PASSWORD_PROPERTY, "test");
((javax.xml.rpc.Stub)proxy.getUserServiceSoap())._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, "http://liferayserver:8080/tunnel-web/secure/axis/Portal_UserService");
com.liferay.portal.model.UserSoap user = proxy.getUserById(10129);

response.getWriter().write(user.getEmailAddress());


Note that setting username, password, and the endpoint is required.

The Netbeans code that didn't work looked like this:

try {
client.UserServiceSoapService userServiceSoapService = new client.UserServiceSoapService_Impl();
client.UserServiceSoap portal_UserService = userServiceSoapService.getPortal_UserService();
((javax.xml.rpc.Stub)portal_UserService)._setProperty(javax.xml.rpc.Stub.USERNAME_PROPERTY, "10129");
((javax.xml.rpc.Stub)portal_UserService)._setProperty(javax.xml.rpc.Stub.PASSWORD_PROPERTY, "test");
((javax.xml.rpc.Stub)portal_UserService)._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, "http://liferayserver:8080/tunnel-web/secure/axis/Portal_UserService");
response.getWriter().write(user.getEmailAddress());
} catch(javax.xml.rpc.ServiceException ex) {
java.util.logging.Logger.getLogger(client.UserServiceSoapService.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch(java.rmi.RemoteException ex) {
java.util.logging.Logger.getLogger(client.UserServiceSoapService.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch(Exception ex) {
java.util.logging.Logger.getLogger(client.UserServiceSoapService.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}

Note that the calls look almost identical here, it's just that the client generated by Netbeans has deserialization issues for whatever reason.

Sorry about the bad code formatting, I don't know how to fix it with this crappy blogger editor.

Sunday, October 26, 2008

Eclipse Ganymede WTP Can Bite Me

****
I am an idiot.

The J2EE module dependencies of my project were reset when I did the renaming business. It took me an embarrassingly long time to figure this out, but I wasn't exactly helped much by Eclipse's awesome "Preferences" pages.
****

Approximately seven hours down the tubes tonight fighting with Eclipse WTP (Web Tools Platform). Everything was working fine earlier, but then I used Eclipse's own refactoring tools to rename a few projects and the whole thing went belly up. For some reason it's no longer publishing my projects properly to tomcat and I'm getting persistent ClassNotFound exceptions for classes that are not in the project that I'm actually publishing.

Build environment seems ok, all of my unit tests run fine, including tests of the Dynamic Web Project in question which references classes another Utility project, which are ultimately not found... everything works except for the publishing & running part. I can successfully create a new test client via Web Services and the client JSP pages load and fire, but when I hit the Invoke button: blammo, ClassNotFoundException: com.you.are.an.idiot.Haha not found.

I went so far as to completely wipe Eclipse and reinstall. I then re-created my workspace and projects and imported the source. I even ditched Tomcat and let Eclipse install a new one for me. Nothing. It's all hosed and I'm mad as hell.

Welp, I get to look like an ass in the morning because my working code isn't demonstratable. Sure wish I knew what happened, but don't really care. I'm giving JDeveloper a download. Sorry Eclipse, I appreciate the vision and hard work, but most of the stuff I've tried outside of the core featureset has been way too fragile.

Eclipse... *snif* ... what really chaps my ass is that this crap was working this afternoon and I was just starting to dig in and refine the interface for this project. If only I hadn't decided to friggin RENAME some projects... By now I would likely be finished.... but here I am, without a clue how to proceed without launching in to a completely different environment.

If anybody knows of a secret "clean up everything related to Eclipse and every damn piece of configuration it's ever puked up and start over from scratch" button, I'm all ears. I'm pretty sure I covered everything when I started over, but I must've missed something.