Open Office reads Microsoft Word 2007 documents out of the box. Mac OSX comes with an unzip utility out of the box so it would make sense you receive on your MAC a zipped Word 2007 document and you will read it without any problems.
The reality is that at least in my latest Mac Book Pro (2009) when I double click the zip file it gets extracted in a folder full of XML files which Open Office will not recognize.
Of course from command prompt your old friend "unzip" will do nothing more than extracting your file but Finder will not. Somehow it is so smart that it will decompress the doc file as well (Yes the .doc you get from Microsoft 2007 is no more than a zipped bundle of XML files and more)
Now, if you are on a MAC you love GUI ;-) and so allow me to recommend http://www.edenwaith.com/products/guitar/ for uncompressing. It is a wrapper of command line utilities that do not go any smarter than what you need.
Wednesday, July 22, 2009
Wednesday, June 24, 2009
Windows Mobile, Outlook/Exchange and Google Contacts/Calendar Synchronization
There is no need to pay for any service or program to keep your Google calendar and contacts synchronized with those in your pocket-pc and your Windows Desktop OS.
1. Visit "Google Help › Mobile Help › Using Your Device › Windows Mobile Devices › Google Sync" and get instructions to set up your mobile device.
2. Visit "Google Help › Google Calendar Help › Access options › Sync › Sync with Microsoft Outlook › Google Calendar Sync: Overview" to download and install in your Windows Desktop OS "Google Calendar Sync"
3. Calendars are synchronized between all parts without problems. Contacts though is a different story. For contacts you will need to synchronize from the mobile device to Google and your Exchange Corporate Server, that way your ActiveSync will necessarily be the master as of the time of this writing not direct sync between Google and Exchange is still available.
From now on you can manage your contacts or calendar from either Microsoft Outlook, your mobile phone or Google Web interface.
1. Visit "Google Help › Mobile Help › Using Your Device › Windows Mobile Devices › Google Sync" and get instructions to set up your mobile device.
2. Visit "Google Help › Google Calendar Help › Access options › Sync › Sync with Microsoft Outlook › Google Calendar Sync: Overview" to download and install in your Windows Desktop OS "Google Calendar Sync"
3. Calendars are synchronized between all parts without problems. Contacts though is a different story. For contacts you will need to synchronize from the mobile device to Google and your Exchange Corporate Server, that way your ActiveSync will necessarily be the master as of the time of this writing not direct sync between Google and Exchange is still available.
From now on you can manage your contacts or calendar from either Microsoft Outlook, your mobile phone or Google Web interface.
Wednesday, March 25, 2009
Submitting Iphone Application to iTunes
Well this proved to be a little bit complicated but it shouldn't be if you carefully follow at least one time all the steps from IPhone developer Program ("Distribution|Prepare App" has all necessary instructions). Anyway here are some important and very basic steps to follow.
The major problem I got was "application failed codesign verification" after trying to send the binary from App Loader.
Just be sure you follow careful all steps from IPhone developer Program ("Distribution|Prepare App" has them all). The error is very generic and anything you miss will stop your app from being sent to Apple. In my case I was working with the 'Project Info Window' (Menu | Project | Edit Project Settings) all the time, ignoring that many of the steps involve using the 'Target Info Window' (Menu | Project | Edit Active Target)
As a side note the application I was working on had a lot of local resources and being almost 40MB it took 15 minutes to get uploaded. It was not my Internet Connection for sure but just an Apple throughput limitation.
1. In XCode navigate to Products/${appname}.app. CTRL + click on top of it and select " Reveal in Finder"
2. In the Finder Window use CTRL + click on top of ${appname}.app and select "compress"
3. Open App Loader and select Menu | File | New and choose your application
4. Follow steps and point to the binary (zip created above)
5. Press Send.
The major problem I got was "application failed codesign verification" after trying to send the binary from App Loader.
Just be sure you follow careful all steps from IPhone developer Program ("Distribution|Prepare App" has them all). The error is very generic and anything you miss will stop your app from being sent to Apple. In my case I was working with the 'Project Info Window' (Menu | Project | Edit Project Settings) all the time, ignoring that many of the steps involve using the 'Target Info Window' (Menu | Project | Edit Active Target)
As a side note the application I was working on had a lot of local resources and being almost 40MB it took 15 minutes to get uploaded. It was not my Internet Connection for sure but just an Apple throughput limitation.
JQuery Tooltip for Html Select Boxes
Sometimes there is limited content width for options showing up in an HTML Select tag. Consider using in those cases JQuery Tooltip plugin:
<!-- Include jquery and tooltip plugin -->
<script src="jquery-1.2.6.js" type="text/javascript"></script>
<script src="jquery.tooltip.js" type="text/javascript"></script>
<!-- Forcing a narrow select box -->
<style type="text/css">
select{
width: 60;
}
option{
width: 60;
}
</style>
<!-- Include custom code to handle the tooltip -->
<script type="text/javascript">
//After loading the page insert the title attribute.
$(function(){
$("select option").attr( "title", "" );
$("select option").each(function(i){
this.title = this.text;
})
});
//Attach a tooltip to select elements
$("select").tooltip({
left: 25
});
</script>
<!-- When moving the mouse over the below options -->
<select>
<option>very long option text 1</option>
<option>very long option text 2</option>
<option>very long option text 3</option>
<option>very long option text 4</option>
<option>very long option text 5</option>
<option>very long option text 6</option>
</select>
Tuesday, March 10, 2009
Unicode Support in Web applications
UPDATE: While most of the points below are still true as of March 2014 the one thing you should do is to visit your whole stack for "Unicode" support. For example looking for tomcat you get this.
Regardless which programming language you use and what application server is involved, internationalization (i18n) support is about handling character encoding in a proper way. Below are guidelines to take into account for any combination of WEB Server/Language. Examples are shown for JBoss/Java though.
1. REQUEST ENCODING: Do not touch it in the server side. Do not use request.setCharacterEncoding() if you do not understand the implication. Only the client (browser) knows the supported encoding and it should be the only responsible for setting it. Most of the browsers use "ISO-8859-1" encoding when submitting data but for example using HTML FORM accept-charset attribute this encoding could be different. JBoss (4.0.4-GA at least) will not affect a GET request when request.setCharacterEncoding() is used but it will affect the POST parameters. It is clear that somehow the algorithm used to decode the query string is different than the one used for posted form data. By default, at least in my tests, request.getCharacterEncoding() returns always NULL.
2. REQUEST PARAMETERS PARSING: Browsers will encode "ISO-8859-1" even those characters not supported by that encoding. Be aware of your server limitations. A typical Servlet Container will try to interpret any request as "ISO-8859-1" and so corrupted bytes are going to end up in the String returned by ServletRequest.getParameter(). The good news is bytes can be read from that corrupted string and reencoded with the right encoding (the one you support in your application and I would say it should be 99% percent of the time UTF-8). To correct this issue wrap ServletRequest.getParameter() following http://www.adobe.com/devnet/server_archive/articles/internationalization_in_jrun.html advice. Notice however that it is assumed in that post that Browsers will always use "ISO-8859-1". A safer way is to find the encoding as below:
If you are using Tomcat you can avoid that all together with a a change in server.xml and the use of a CharacterEncodingFilter. These features should be available in other servers as well. So again use the below which will deal with GET requests:
this issue (https://advancenative2asciitool.dev.java.net/). Below is a class that turns the Unicode characters into ASCII Java Escaped Unicode:
4. RESPONSE HEADERS: An HTTP header (Content-Type) is responsible to give the client (Browser) the encoding used in the response. A typical example is "Content-Type: text/html; charset=UTF-8". The response content type then must be set not only with the mime type you want but in case of any text mime type the proper charset must be specified as well.
From JSP for example:
There is no need to call response.setCharacterEncoding() if setContentType() is called passing both the mime type (text/html) and the encoding (charset). If response.setCharacterEncoding("UTF-8") is used then still setContentType("text/html")must be called. Refer to http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletResponse.html#setCharacterEncoding(java.lang.String) for more explanation.
If you can identify if the request should be served as html in a Servlet Filter then it is a good idea to build a Unicode filter that will force the response to be UTF-8 for those requests:
5. RESPONSE CONTENT: Of course you must ensure all the body of the HTTP response uses the specified by RESPONSE HEADER encoding. This is not a big problem in Java but again there are subtle problems you need to be aware of. It is common for example to use JSP to specify markup. If the HTML included in the JSP needs non-ascii unicode characters then the encoding of the file must be the same as the one used in the responses AND as explained before an @page directive with contentType specified in it is required in absolutely all JSP pages. Add to the equation any file touched by building tools regardless if you use Maven, Ant, Make, Shell, manual, you-name-it methods. Any piece of information returned after the HTTP headers must be encoded as dictated by "Content-Type" header. So my advice is encode all your source files in UTF-8 if you need to support internationalization in your application. Finally, be sure your Server is running with default encoding set to UTF-8. Commonly this is not a problem in current versions of Linux where the default charset is precisely "UTF-8" but Windows uses "ISO-8859-1". In the case of Java Applications use the below when starting the server:
You can always check from JSP the server encoding:
6. DEFAULT RESPONSE ENCODING: There are server specific configurations that will free the developer from setting the charset of the response. I do not recommend them since they break portability and might end up generating other problems related to internationalization.
7. BROWSER / OS language support: Firefox for example comes with support for all languages however Internet Explorer does not. Commonly WXP users running IE will need to install language support for Chinese and Thai, Font support in IE is tricky (Internet Options|General|Fonts|Latin Based;Times New Roman OR Arial;Courier New is a good selection, any other is not good for Unicode support), support for Assian languages must be selected manually (Control Panel | windows Regional and Language Options | Install files for 'East Asian Languages')
8. FILE ENCODING: If developers use Windows and Linux then default encoding in their Editors will be an issue. Linux uses UTF-8. Do not use non-ASCII characters in code if you are not able to force the use of UTF-8 from editors. If specific non ASCII code is needed for String comparison for example you can use escaped UTF-16 sequences for example in Java instead of ÀÁÂÃÄ use \u00c0\u00c1\u00c2\u00c3\u00c4
Here is an excellent Unicode table.
9. JDBC: If you are interacting with your database which is already storing UTF-8 successfully then it is time to tell your driver to use Unicode as well. Here is a typical URL for MySQL:
10. FRAMEWORKS: Look for support of Unicode if you are using a specific Framework. For example in Spring org.springframework.web.filter.CharacterEncodingFilter will encode requests and responses.
Regardless which programming language you use and what application server is involved, internationalization (i18n) support is about handling character encoding in a proper way. Below are guidelines to take into account for any combination of WEB Server/Language. Examples are shown for JBoss/Java though.
1. REQUEST ENCODING: Do not touch it in the server side. Do not use request.setCharacterEncoding() if you do not understand the implication. Only the client (browser) knows the supported encoding and it should be the only responsible for setting it. Most of the browsers use "ISO-8859-1" encoding when submitting data but for example using HTML FORM accept-charset attribute this encoding could be different. JBoss (4.0.4-GA at least) will not affect a GET request when request.setCharacterEncoding() is used but it will affect the POST parameters. It is clear that somehow the algorithm used to decode the query string is different than the one used for posted form data. By default, at least in my tests, request.getCharacterEncoding() returns always NULL.
2. REQUEST PARAMETERS PARSING: Browsers will encode "ISO-8859-1" even those characters not supported by that encoding. Be aware of your server limitations. A typical Servlet Container will try to interpret any request as "ISO-8859-1" and so corrupted bytes are going to end up in the String returned by ServletRequest.getParameter(). The good news is bytes can be read from that corrupted string and reencoded with the right encoding (the one you support in your application and I would say it should be 99% percent of the time UTF-8). To correct this issue wrap ServletRequest.getParameter() following http://www.adobe.com/devnet/server_archive/articles/internationalization_in_jrun.html advice. Notice however that it is assumed in that post that Browsers will always use "ISO-8859-1". A safer way is to find the encoding as below:
String requestEncoding = request.getCharacterEncoding();
if(requestEncoding == null || requestEncoding.trim().length() == 0) {
requestEncoding = "ISO-8859-1";
}
If you are using Tomcat you can avoid that all together with a a change in server.xml and the use of a CharacterEncodingFilter. These features should be available in other servers as well. So again use the below which will deal with GET requests:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>And the below which will deal with POST requests:
<!-- First fileter must be the Set Character Encoding Filter -->
<filter>
<filter-name>setCharacterFilter</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
3. PROGRAM MANIPULATION: Java has unicode support out of the box but not all classes are privileged to enjoy it. Be careful when working with Properties.class as UTF-8 is not allowed. If UTF-8 support is needed then it must be escaped in properties files. We need then to convert UTF-8 strings into ASCII Java Escaped Unicode. For example the two Asian characters string "中医" (URL Encoded version: %E4%B8%AD%E5%8C%BB) should be converted to \u00ef\u00bb\u00bf\u00e4\u00b8\u00ad\u00e5\u0152\u00bb removing all but the first "\u" before using Properties#load() . There is a project with source code available that can be used to work aroundthis issue (https://advancenative2asciitool.dev.java.net/). Below is a class that turns the Unicode characters into ASCII Java Escaped Unicode:
/**
* All credits for the "Advance Native2ASCII Tool" from https://advancenative2asciitool.dev.java.net/
*/
package com.bittime.util.design;
/**
* Please refer to http://en.wikipedia.org/wiki/ASCII for definition on valid/printable ASCII characters
*/
public class Unicode2ASCII {
public static String toHTML(String unicode)
{
String tc = unicode;
String output = "";
char[] ca = tc.toCharArray();
int x;
for( x = 0; x < a =" ca[x];">126){
output += "&#" + (int)a + ";" ;
}
else{
output += a ;
}
}
return output;
}
public static String toJAVA(String unicode)
{
String tc = unicode;
String output = "";
char[] ca = tc.toCharArray();
int x;
for( x = 0; x < a =" ca[x];">255){
String hexString = "0000" + Integer.toHexString((int)a);
hexString = hexString.substring(hexString.length() - 4);
output += "\\u" + hexString ;
}
else{
output += a ;
}
}
return output;
}
}
4. RESPONSE HEADERS: An HTTP header (Content-Type) is responsible to give the client (Browser) the encoding used in the response. A typical example is "Content-Type: text/html; charset=UTF-8". The response content type then must be set not only with the mime type you want but in case of any text mime type the proper charset must be specified as well.
From JSP for example:
<%@page contentType="text/html; charset=UTF-8" %>From Java:
response.setContentType("text/html; charset=UTF-8");
There is no need to call response.setCharacterEncoding() if setContentType() is called passing both the mime type (text/html) and the encoding (charset). If response.setCharacterEncoding("UTF-8") is used then still setContentType("text/html")must be called. Refer to http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletResponse.html#setCharacterEncoding(java.lang.String) for more explanation.
If you can identify if the request should be served as html in a Servlet Filter then it is a good idea to build a Unicode filter that will force the response to be UTF-8 for those requests:
public class UnicodeFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
response.setContentType("text/html; charset=UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
}
5. RESPONSE CONTENT: Of course you must ensure all the body of the HTTP response uses the specified by RESPONSE HEADER encoding. This is not a big problem in Java but again there are subtle problems you need to be aware of. It is common for example to use JSP to specify markup. If the HTML included in the JSP needs non-ascii unicode characters then the encoding of the file must be the same as the one used in the responses AND as explained before an @page directive with contentType specified in it is required in absolutely all JSP pages. Add to the equation any file touched by building tools regardless if you use Maven, Ant, Make, Shell, manual, you-name-it methods. Any piece of information returned after the HTTP headers must be encoded as dictated by "Content-Type" header. So my advice is encode all your source files in UTF-8 if you need to support internationalization in your application. Finally, be sure your Server is running with default encoding set to UTF-8. Commonly this is not a problem in current versions of Linux where the default charset is precisely "UTF-8" but Windows uses "ISO-8859-1". In the case of Java Applications use the below when starting the server:
-Dfile.encoding=UTF-8Particularly for JBoss Windows for example:
set JAVA_OPTS=-Dfile.encoding=UTF-8 %JAVA_OPTS%
You can always check from JSP the server encoding:
%=System.getProperty("file.encoding")%>
6. DEFAULT RESPONSE ENCODING: There are server specific configurations that will free the developer from setting the charset of the response. I do not recommend them since they break portability and might end up generating other problems related to internationalization.
7. BROWSER / OS language support: Firefox for example comes with support for all languages however Internet Explorer does not. Commonly WXP users running IE will need to install language support for Chinese and Thai, Font support in IE is tricky (Internet Options|General|Fonts|Latin Based;Times New Roman OR Arial;Courier New is a good selection, any other is not good for Unicode support), support for Assian languages must be selected manually (Control Panel | windows Regional and Language Options | Install files for 'East Asian Languages')
8. FILE ENCODING: If developers use Windows and Linux then default encoding in their Editors will be an issue. Linux uses UTF-8. Do not use non-ASCII characters in code if you are not able to force the use of UTF-8 from editors. If specific non ASCII code is needed for String comparison for example you can use escaped UTF-16 sequences for example in Java instead of ÀÁÂÃÄ use \u00c0\u00c1\u00c2\u00c3\u00c4
Here is an excellent Unicode table.
9. JDBC: If you are interacting with your database which is already storing UTF-8 successfully then it is time to tell your driver to use Unicode as well. Here is a typical URL for MySQL:
jdbc.url=jdbc:mysql://localhost:3306/myDB?Unicode=true&characterEncoding=UTF-8
10. FRAMEWORKS: Look for support of Unicode if you are using a specific Framework. For example in Spring org.springframework.web.filter.CharacterEncodingFilter will encode requests and responses.
Wednesday, March 04, 2009
Building Web Services Clients
When building Web Services (SOAP WS) clients in Java or any other language there are a couple of good tools to get familiar with before you drop your first line of code.
The two needed tools are a MockUp service that can be built from the WSDL of the remote web service and an HTTP Sniffer. While you can find similar tools written in a variety of languages the two that I am presenting hereare written in Java and thanks to that they run in any major OS out there by this time.
No matter what you use (DotNet client, RoR client, PHP Client, Spring-WS, AXIS2, AXIS, etc) the steps below should help you.
Prerequisites
1. SOAPUI
1. tcpmon
Use Cases
Writting use cases is important so you know every detail as to how your application should work. They are also a perfect initial documentation that even if outdated in the future at least gives other developers comming after you or even to yourself a reminder as to what the application does.
Building the Mockup Services (necessary to simulate Use Cases)
1. Start from understanding the services and ending points we will use from the remote service. In other words visit the WSDLs (for example https://domain/some/path/descriptor?wsdl)
2. Use SOAPUI to create a new project giving the WSDLs (File|New Project|Provide WSDL and a name|Check "Create Requests" and "Create MockService").
3. Locate from the Request group the remote method to invoke and double click on "Request 1". Complete the request parameters if any and click on the "Run" button
4. Right click on the root of the resulting entry on the right panel and click on "Generate MockService". Locate from the MockService group the remote method to invoke and double click on "Response1"
5. Copy the response text from the right pane of the request window into the right pane of the response window.
6. Repeat the above for any single method you want to Mock up (simulate)
7. Double click on the MockService group (or right click and select "Show MockService Editor"). Hit the "Run" button and the service will be available on port 8088
8. At this point from the Request window the address can be changed to point to the local Mock Service listening on port 8088. Hit the green button called "Submit request ...". The right pane should show up whatever the Response window right pane contains
Using tcpmon
This is a java utility which comes with Axis (not Axis2). To run it use something like:
With the commands above you get a window where you can see the TCP traffic going back and forth to port 8081. That port is proxing port 8088 meaning that requests to made to 8081 are actually forwarded to 8088.
Just go back to SOAPUI and click on any "Request 1" window address bar, pick the local address of the mockup service. Click again on the address bar and select "edit current", change the port number to 8081. After hitting the 'Run' button you can see the response on SOAPUI but you can also get the whole request and response including HTTP headers from tcpmon. Of course this is not that useful because you have all that information from SOAPUI already but when you start building your client you will not longer see your requests on SOAPUI.
The two needed tools are a MockUp service that can be built from the WSDL of the remote web service and an HTTP Sniffer. While you can find similar tools written in a variety of languages the two that I am presenting hereare written in Java and thanks to that they run in any major OS out there by this time.
No matter what you use (DotNet client, RoR client, PHP Client, Spring-WS, AXIS2, AXIS, etc) the steps below should help you.
Prerequisites
1. SOAPUI
1. tcpmon
Use Cases
Writting use cases is important so you know every detail as to how your application should work. They are also a perfect initial documentation that even if outdated in the future at least gives other developers comming after you or even to yourself a reminder as to what the application does.
Building the Mockup Services (necessary to simulate Use Cases)
1. Start from understanding the services and ending points we will use from the remote service. In other words visit the WSDLs (for example https://domain/some/path/descriptor?wsdl)
2. Use SOAPUI to create a new project giving the WSDLs (File|New Project|Provide WSDL and a name|Check "Create Requests" and "Create MockService").
3. Locate from the Request group the remote method to invoke and double click on "Request 1". Complete the request parameters if any and click on the "Run" button
4. Right click on the root of the resulting entry on the right panel and click on "Generate MockService". Locate from the MockService group the remote method to invoke and double click on "Response1"
5. Copy the response text from the right pane of the request window into the right pane of the response window.
6. Repeat the above for any single method you want to Mock up (simulate)
7. Double click on the MockService group (or right click and select "Show MockService Editor"). Hit the "Run" button and the service will be available on port 8088
8. At this point from the Request window the address can be changed to point to the local Mock Service listening on port 8088. Hit the green button called "Submit request ...". The right pane should show up whatever the Response window right pane contains
Using tcpmon
This is a java utility which comes with Axis (not Axis2). To run it use something like:
AXIS_LIB="/home/nurquiza/libraries/axis-1_4/lib"
CLASSPATH="$AXIS_LIB/wsdl4j-1.5.1.jar:$AXIS_LIB/axis.jar:$AXIS_LIB/jaxrpc.jar:$AXIS_LIB/commons-logging-1.0.4.jar:$AXIS_LIB/commons-discovery-0.2.jar:$AXIS_LIB/saaj.jar"
java -cp $CLASSPATH org.apache.axis.utils.tcpmon 8081 localhost 8088 &
With the commands above you get a window where you can see the TCP traffic going back and forth to port 8081. That port is proxing port 8088 meaning that requests to made to 8081 are actually forwarded to 8088.
Just go back to SOAPUI and click on any "Request 1" window address bar, pick the local address of the mockup service. Click again on the address bar and select "edit current", change the port number to 8081. After hitting the 'Run' button you can see the response on SOAPUI but you can also get the whole request and response including HTTP headers from tcpmon. Of course this is not that useful because you have all that information from SOAPUI already but when you start building your client you will not longer see your requests on SOAPUI.
Tuesday, March 03, 2009
DotNet Web Services From Axis2
I had to connect recently to some DotNet Web Services that were returning node names starting with an upper case (as a difference with Java where nodes start with lower case as Java class members do). I already posted a project about this but just wanted to conclude here.
This situation generates a problem at least forthe latest Axis2-1.4.1 which will be unable to dynamically deserialize the response (Assumming BeanUtil#deserialize() is used here). I have described this problem (http://markmail.org/message/2d2r7qlwnoeqka5m) in the mailing list (org.apache.ws.axis-dev).
For unmarshalling or deserializing XML into Java objects there are several Object-to-XML mapping (OXM) libraries: JAXB, JiBX, XMLBeans, Castor, XStream. Most of them are supported by Spring Web Services (Spring-WS) which provides a full stack to build and consume web services.
Another solution is going low level and use SAX (Simple API for XML), StAX (the streaming API for XML).
I have successfully worked around this issue using JAXB. The only reason that stopped me from using Sprint-WS was to stick to the old implementation code for the client (written using ADB stubs)
Using JAXB
1. Download JAXB and follow instructions from the site.
2. From the JAXB lib folder generate the classes from schema like in:
java -jar jaxb-xjc.jar -p com.nestorurquiza.axis2.samople.client.jaxb "https://mydomain/some/path/serviceShema.xsd" -d /path/to/project/client/jaxb/
3. You end up with generated classes that can be used from the client code to unmarshal the SOAP service response into Java objects. Below is a snippet as to how to get it working starting from an OMElement (Refer to my previous tutorial about Axis2 Dynamic Web Services). We are marshalling 'SampleObject' below. Note that SampleObject' is actually a class generated from the schema as explained before:
Again, should the current Axis2 Axiom API work with node names starting with upper case we should have avoid all of the above JAXB code and just use:
Here are the dependencies I successfully used:
This situation generates a problem at least forthe latest Axis2-1.4.1 which will be unable to dynamically deserialize the response (Assumming BeanUtil#deserialize() is used here). I have described this problem (http://markmail.org/message/2d2r7qlwnoeqka5m) in the mailing list (org.apache.ws.axis-dev).
For unmarshalling or deserializing XML into Java objects there are several Object-to-XML mapping (OXM) libraries: JAXB, JiBX, XMLBeans, Castor, XStream. Most of them are supported by Spring Web Services (Spring-WS) which provides a full stack to build and consume web services.
Another solution is going low level and use SAX (Simple API for XML), StAX (the streaming API for XML).
I have successfully worked around this issue using JAXB. The only reason that stopped me from using Sprint-WS was to stick to the old implementation code for the client (written using ADB stubs)
Using JAXB
1. Download JAXB and follow instructions from the site.
2. From the JAXB lib folder generate the classes from schema like in:
java -jar jaxb-xjc.jar -p com.nestorurquiza.axis2.samople.client.jaxb "https://mydomain/some/path/serviceShema.xsd" -d /path/to/project/client/jaxb/
3. You end up with generated classes that can be used from the client code to unmarshal the SOAP service response into Java objects. Below is a snippet as to how to get it working starting from an OMElement (Refer to my previous tutorial about Axis2 Dynamic Web Services). We are marshalling 'SampleObject' below. Note that SampleObject' is actually a class generated from the schema as explained before:
import org.apache.axiom.om.OMElement;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import java.io.Reader;
import java.io.StringReader;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import com.nestorurquiza.axis2.sample.client.jaxb.SimpleObject;
...
//AXIOM stuff ...
OMElement result = sender.sendReceive(sampleObjectPayload);
OMElement firstElement = result.getFirstElement();
//The data element is a child of the first element for this example
OMElement dataElement = firstElement.getFirstElement();
//JAXB stuff ... Contextualize JAXB within the package holding the generated from schema sources
JAXBContext jc = JAXBContext.newInstance("com.nestorurquiza.axis2.sample.client.jaxb");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Reader reader = new StringReader(dataElement.toString());
Source source = new StreamSource(reader);
//JAXB always unmarshals to a JAXBElement. Notice the below will work even if the XML node has a different name than the class.
//If the node and the class are named the same then just use SampleObject sampleObject = unmarshaller.unmarshal(source); instead.
JAXBElementroot = unmarshaller.unmarshal(source, SampleObject.class);
SampleObject sampleObject = root.getValue();
//Let us retrieve one of the members from our 'SampleObject'. Note the use of getValue().
String sampleObjectMember = sampleObject.getSampleObjectMember().getValue();
//We can use our String member now
System.out.println("sampleObjectMember: " + sampleObjectMember);
...
SampleObject sampleObject = (SampleObject) BeanUtil.deserialize(SampleObject.class, dataElement, new DefaultObjectSupplier(), "SampleObject");Dependencies
Here are the dependencies I successfully used:
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-adb</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-tools</artifactId>
<version>2.1.3</version>
</dependency>
Subscribe to:
Posts (Atom)