tag:blogger.com,1999:blog-77711390356312720632024-03-08T02:37:44.565-08:00Amila's BlogsAmila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.comBlogger28125tag:blogger.com,1999:blog-7771139035631272063.post-32839643626417223292012-09-01T19:34:00.000-07:002012-09-01T19:48:57.159-07:00ESB performance<div dir="ltr" style="text-align: left;" trbidi="on">
I recently happen to do some performance tests with a system having a back end service and an ESB proxy service passing the message through that. In real case it needs to route the message using http headers but to measure the performance, it is reasonable just to use it as a pass through proxy. The problem was when the message route through the ESB the system performance get reduced.
<br/>
First I created an <a href="http://people.apache.org/~amilas/performance/PerfService.aar">back end service</a> using an ADB axis2 service and deployed that in WSO2 AS 4.1.2. Then I measure the throughput of this service with a <a href="http://people.apache.org/~amilas/performance/request_1.xml">message with 780 bytes</a> using java bench tool. It had around 13,000 TPS. Here I used 500,000 messages with difference concurrency levels (For this I edit the mgt-transports.xml file to increase the threads).
<br/>
<br/>
-n 500 -c 1000 - 13,140.52
<br/>
-n 1000 -c 500 - 13,747.96
<br/>
-n 2000 -c 250 - 13,004.18
<br/>
-n 5000 -c 100 - 13,297.51
<br/>
-n 10000 -c 50 - 13,039.79
<br/>
<br/>
Then I created a proxy service using WSO2 ESB 4.0.3 and enable the binary relay (<a href="http://people.apache.org/~amilas/performance/axis2.xml">This can be done by editing the axis2.xml and setting the correct builder and formatter</a>) to send a message through ESB. Then I measure the performance of this system again with 500,000 messages using java bench. Here are the results.
<br/>
<br/>
-n 500 -c 1000 - 1,179.16
<br/>
-n 1000 -c 500 - 1,360.03
<br/>
-n 2000 -c 250 - 1,471.56
<br/>
-n 5000 -c 100 - 1,532.91
<br/>
-n 10000 -c 50 - 1,526.42
<br/>
<br/>
It has reduced the performance around 8 times. After talking to different people I found that the ESB performance can be fine tuned as given <a href="http://wso2.org/library/articles/2012/03/wso2-esb-message-transfer-mechanisms-comparative-benchmarks#configuringtheesb">here</a>. Basically this increases the threads to maximize the performance. After starting the server with these parameters it gave me an exception saying too many open files. In order to fix this I had to increase the OS level threads as follows.
<br/>
<br/>
1. Increased the number of file handlers
<br/>
sudo vi /etc/sysctl.conf
<br/>
fs.file-max = 1000000
<br/>
fs.inotify.max_user_watches = 1000000
<br/>
<br/>
2. Increase the number of files to user
<br/>
sudo vi /etc/security/limits.conf
<br/>
amila soft nofile 100000
<br/>
amila hard nofile 100000
<br/>
<br/>
These two fixed the above problem and I could start the server successfully. Then I ran the earlier test again. Here is the results.
<br/>
<br/>
-n 500 -c 1000 - 5,562.29
<br/>
-n 1000 -c 500 - 5,628.08
<br/>
-n 2000 -c 250 - 5,679.52
<br/>
-n 5000 -c 100 - 5,609.53
<br/>
-n 10000 -c 50 - 5,159.77
<br/>
<br/>
In this case it was around 4 time increment of the performance. But still it is half of the direct back end performance. In this point after running with different options I concluded this as an I/O issue since the message now have to go through an extra hop. I ran all tests in my machine.
<br/>
Then I thought of comparing these results with another ESB to check my above assumption. For that I choose UltraESB 1.7.1 since it has claimed over 2 times performance gain for a direct proxy invocation <a href="http://esbperformance.org/display/comparison/ESB+Performance+Testing+-+Round+6">here</a>. Then I added some extra jars as given in the performance tool site. Then ran the tests with a direct proxy service and here were the results.
<br/>
<br/>
-n 500 -c 1000 - 4,591.54
<br/>
-n 1000 -c 500 - 3,797.29
<br/>
-n 2000 -c 250 - 2,826.34
<br/>
-n 5000 -c 100 - 1,516.03
<br/>
-n 10000 -c 50 - 1,140.33
<br/>
<br/>
Here for some reason it shows very low performance at low concurrency levels and increase with the concurrency. Generally systems shows low performance at low concurrency but I think 50 is a sufficiently enough concurrency level. The other observation I made in this regard was the load average factor with the top tool in linux. It was kept on increasing through out the whole tests. This may be due to not fine tuning the server. However I could not find any document for that. In the given documents it was mentioned that detect the available processors automatically and adjust the parameters accordingly.
<br/>
Then I tried with the zeroCopyEnabled since there was a claim for its high efficiency. Again there was not much difference from the results. Still there is no any significant performance improvement.
<br/>
<br/>
-n 500 -c 1000 - 4,602.64
<br/>
-n 1000 -c 500 - 3,774.64
<br/>
-n 2000 -c 250 - 2,644.13
<br/>
-n 5000 -c 100 - 1,538.64
<br/>
-n 10000 -c 50 - 1,123.28
<br/>
<br/>
After this I was thinking why this test shows a complete different result compared to bench mark results given. One of the observation I made was the low number of messages which may not have produced the consistent results. Although when doing a performance test it is required to send large amount of messages to obtain consistent results there is no reason it always shows a better performance of one ESB always as well. And also there is a possibility of WSO2 ESB is not being tuned for the performance. According to the above results after fine tuning it has showed higher performance.
<br/>
In summary I learned two things from this. First routing through an ESB always degrade the TPS of the system due to additional I/O. Secondly it is always better to measure the performance with the required system in the hardware it suppose to run instead of being rely on the performance bench marks.
<br/>
<br /></div>
Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com9tag:blogger.com,1999:blog-7771139035631272063.post-43881342132812317242010-04-16T23:53:00.000-07:002010-04-16T23:54:06.338-07:00Java Security ModelAn OS process runs under the privileges of the user who fork the process. Therefore under normal conditions a java applications also runs under the privileges of the user who starts it. But there are situations where some privileges of the person who starts it should not be granted to the java application and only set of java code should give the privilege access. <br />Java security model provides a solution for this problem. It let users to specify a set of granted permissions and act as a additional security layer between java application and OS allowing only granted permissions. <br />To understand the concepts lets use the following sample program which creates the file test/test.txt.<br />public class CreateFile {<br /> public void createFile(){<br /> File file = new File("test/test.txt");<br /> try {<br /> System.out.println("Creating file ==> " + file.getAbsolutePath());<br /> file.createNewFile();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> }<br /> public static void main(String[] args) {<br /> new CreateFile().createFile();<br /> }<br />}<br />Now lets run the program with the following command as a normal user<br />java -classpath classes/ com.test.security.CreateFile<br /><br />This would create the file without any problem in the test directory. Here we ran this program without the security manager. Now lets try to run this program as super user but with the security manager.<br /><br />java -Djava.security.manager -classpath classes/ com.test.security.CreateFile<br />Exception in thread "main" java.security.AccessControlException: access denied (java.util.PropertyPermission user.dir read) <br /> at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264) <br /> at java.security.AccessController.checkPermission(AccessController.java:427) <br /> at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) <br /> at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1285) <br /> at java.lang.System.getProperty(System.java:628) <br /> at java.io.UnixFileSystem.resolve(UnixFileSystem.java:118) <br /> at java.io.File.getAbsolutePath(File.java:473) <br /> at com.test.security.CreateFile.createFile(CreateFile.java:27) <br /> at com.test.security.CreateFile.main(CreateFile.java:35) <br /><br />So Even this simple operation runs as the super user it is not allowed to create the file. When a program runs under the security manager it only exposes the security permissions allowed in the security policy files. This is similar to Linux Capabilities. In this way only the required security permission can be given even the program has to started as super users.<br />Now lets give the necessary permissions to run this program. <br />First lets create the policy file as follows<br />grant {<br /> permission java.util.PropertyPermission "user.dir", "read";<br /> permission java.io.FilePermission "test/test.txt", "write";<br /> };<br /><br />And now run this program as follows,<br />java -Djava.security.manager -Djava.security.policy=policy/sample.policy -classpath classes/ com.test.security.CreateFile<br /><br />Here the -Djava.security.policy is used to specify the policy file location. Now again file is created successfully.<br /><br />To understand what happens exactly lets implements our own security permission. Here we write a watch tv permission.<br />public class TVPermission extends BasicPermission {<br /> public TVPermission(String name) {<br /> super(name);<br /> }<br /> public TVPermission(String name, String actions) {<br /> super(name, actions);<br /> }<br /> public boolean implies(Permission p) {<br /> boolean isPermitted = false;<br /> if (p instanceof TVPermission){<br /> isPermitted = p.getName().equals(getName())<br /> && p.getActions().equals(getActions());<br /> }<br /> return isPermitted;<br /> }<br />}<br /><br />Any java permission should implements the java.security.Permission interface. Implies is the important method. Actually when someone requests a permission normally java creates a permission object for that object and check for the permission. Lets use this code to check this. <br /><br />public class WatchTV {<br /> public void watchTV() {<br /> TVPermission tvPermission = new TVPermission("chanel-5", "watch");<br /> AccessController.checkPermission(tvPermission);<br /> // other code goes here<br /> }<br /> public static void main(String[] args) {<br /> new WatchTV().watchTV();<br /> }<br />}<br /><br />Now run this program with the following command<br />It gives this exception<br />Exception in thread "main" java.security.AccessControlException: access denied (com.test.permission.TVPermission chanel-5) <br /> at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264) <br /> at java.security.AccessController.checkPermission(AccessController.java:427) <br /> at com.test.security.WatchTV.watchTV(WatchTV.java:27) <br /> at com.test.security.WatchTV.main(WatchTV.java:32)<br /><br />Now lets add this permission to the policy file as follows and run with the policy file.<br />grant {<br /> permission java.util.PropertyPermission "user.dir", "read";<br /> permission java.io.FilePermission "test/test.txt", "write";<br /> permission com.test.permission.TVPermission "chanel-5", "watch";<br /> };<br /><br /> java -Djava.security.manager -Djava.security.policy=policy/sample.policy -classpath classes/ com.test.security.WatchTV<br /><br />Now it executes correctly. Now we can understand how java runtime manage permissions under a security manager. <br />Lets see how actually jdk 1.5 implements the createNewFile method.<br /><br />public boolean createNewFile() throws IOException {<br /> SecurityManager security = System.getSecurityManager();<br /> if (security != null) security.checkWrite(path);<br /> return fs.createFileExclusively(path);<br /> }<br /><br />First it gets the Security manager and if it is not null (i.e when running under security manager) check for the write permission. This checkWrite method is like this,<br />public void checkWrite(String file) {<br /> checkPermission(new FilePermission(file, <br /> SecurityConstants.FILE_WRITE_ACTION));<br /> }<br />public void checkPermission(Permission perm) {<br /> java.security.AccessController.checkPermission(perm);<br /> }<br /><br />This finally calls the AccessController as in earlier sample.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com4tag:blogger.com,1999:blog-7771139035631272063.post-45633955988013367242010-03-09T03:31:00.001-08:002010-03-09T03:31:34.872-08:00Axis2 temp filesAxis2 supports archive based deployment for both services (.aar) and modules (.mar). These files can internally have 'lib' folders to contain the third party libraries of those services. <br />From Axis2 1.5, when Axis2 creates Configuration Context object which happens when the server starts up or service client invocation, it creates a separate folder under the temp folder to store the temp files. This temp folder is taken from the "java.io.tmpdir" system property. <br />For an example if Axis2 1.5 is deployed under tomcat 6.0.24, it creates the following two files under $CATALINA_TMPDIR.<br />axis2-tmp-2165190954418103759.tmp <br />axis2-tmp-2165190954418103759.tmp.lck<br /><br />Axis2 creates .lck files as a temp file which deletes on a jvm exits. <br /><br />File lockFile = new File(tmpDirName, tmpDir.getName() + ".lck");<br />lockFile.createNewFile();<br />lockFile.deleteOnExit();<br /><br />Therefore when the tomcat goes down this .lck file should also be deleted. But the .tmp folder remains. At the next start up time Axis2 searches for .tmp file folders which does not have a corresponding .lck files and deletes them. So there can not be any grow of temp files.<br /><br />One important thing to remember is that Axis2 copies the repository files (.aar and .mar) when ever it creates a configuration context object. Therefore the tmp folder can be grown while in the server running. Obviously this can be stopped by using one configuration context object for all the service invocations.<br /><br />But there are some instances where .lck file is not properly deleted when the jvm exits. For those situations the temp folder can be deleted within the server starts up shell script. For tomcat this can be done adding code to catalina.sh.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com17tag:blogger.com,1999:blog-7771139035631272063.post-55992419218145914692010-03-08T03:22:00.000-08:002010-03-08T03:34:11.505-08:00Queued Transaction processing with WS-RMCouple of years ago I started writing a new WS-RM implementation called Mercury which uses an state machine model to handle the reliability. It was working well for the requirements we had at that time and we have done two releases under the name WSO2 Mercury. But however WSO2 Mercury could not support the user initiated transactions due to a limitation of its storage design. Then that project didn't last too long and WSO2 moved to use Apache Sandesha as its WS-RM implementation for newly developed carbon based products. <br />At that time I was doing my Msc at University of Moratuwa. For my Msc I was looking for an idea and Dr Sanjiva Weerawarana and Mr Paul Fremantle gave me the idea of re engineering the WSO2 mercury code to support transactions by introducing a new transaction based storage API. Then I started researching different types of reliable message delivery models and finally was able to developed a WS-RM protocol which provides application to application reliability using distributed transactions. This model follows a similar pattern as the well known Queued Transaction processing and hence the thesis tile.<br /><br /><span style="font-weight:bold;">Here is the abstract of my Msc Thesis</span><br /><span style="font-style:italic;">With the popularity of the distributed business applications, the application data is distributed in various physical storages. However most of the business transactions require to update data stored in more than one storage. Hence updating two data storages reliably is a common problem for most of the distributed business applications. <br /><br />Queued transaction processing is a concept widely used to achieve such a processing model using intermediate queues to transfer messages reliably. In such a system at the client side, both updating the client storage and writing the message to be sent to the client side message queue happens in the same distributed transaction. Similarly at the server side reading the message from the server side queue and updating the sever storage happens in the same distributed transaction. But such a system may have interoperability problems if client and server use different types of technologies.<br /><br />Web services are used to communicate among the heterogeneous systems by passing SOAP messages using standard transport mechanisms like http. Web services can reliably communicate by using WS-Reliable messaging specification(WS-RM). WS-RM uses concepts of Reliable messaging source (RMS) and Reliable messaging destination (RMD) between which it guarantees reliable message delivery.<br /><br />By combining these two concepts, we introduce an approach to solve the above mentioned problem in an interoperable manner using WS-RM to communicate between nodes while keeping RMS and RMD as intermediate storages. In our model reliable message delivery happens in three phases. First both updating application client storage and writing message to the RMS happens in the same distributed transaction. Then WS-RM protocol reliably transfers the message to RMD at the server side. Finally at the server reading the message from the RMD and updating the server storage happens in the same distributed transaction. The middleware software entity that we developed to encapsulate this approach is called Mercury which implements WS-RM protocol.</span><br /><br /><a href="http://people.apache.org/~amilas/msc/Thesis-Amila%20Suriarachchi-088254P.pdf">Msc Thesis report</a><br /><a href="http://people.apache.org/~amilas/msc/CD.zip">CD copy which provides the source code, binaries and demos</a>Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com0tag:blogger.com,1999:blog-7771139035631272063.post-15139223135389538612010-02-07T23:01:00.000-08:002010-02-07T23:05:55.119-08:00WSO2 WSAS 3.1.3 releasedWSO2 WSAS is an Enterprise ready web service container based on Apache Axis2 and related other libraries such as Rampart, Sandesha2, Transports etc... Then what is the advantage of using WSO2 WSAS rather than using those apache libraries directly?<br /><br />WSO2 WSAS comes with an integrated and tested set of all those libraries so that users do not have to find the compatible libraries and integrate them.<br /><br />WSO2 WSAS Admin console provides the extensive monitoring, management features. <br />The try it can be used to test a web service quickly without generating the stubs. Users can change the log levels through the admin console and can enable request/response message logging in order to check the messages comes in and out. <br />Admin Console can be used to update servers while they are running. I.e users can add parameters, engage modules (there are even sample scenarios to engage Security), apply polices, add transports, add services etc .. WSO2 WSAS persists all these changes to its registry so that it is available even if some one restart the server. This is very useful for services that do not uses a services.xml like jaxws servers.<br />There are some graphical tools called wsdl2java, java2wsdl, WSDL Converter, Try it, Service Validator and Module Validator. <br /><br />WSO2 WSAS 3.1.3 can be downloaded <a href="http://wso2.org/downloads/wsas">here</a>.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com0tag:blogger.com,1999:blog-7771139035631272063.post-24118027566549348652010-01-17T01:08:00.000-08:002010-01-17T01:12:21.223-08:00Improving Axis2 http transport clientUntil Axis2 1.5 a separate http client instance was created per request by default. This leads to an connection timeout problem with the high loads. See <a href="http://amilachinthaka.blogspot.com/2009/05/improving-axis2-client-http-transport.html">here</a> for more details.<br /><br />In order to solve this issue Axis2 1.5.1 uses one http client object cached in configuration context for all requests. Since by default MultiThreadedHttpConnectionManager allows two request per host this causes an issue if tried to invoke a service more than twice.<br /><br />Following options can be taken to solve this issue.<br />1.set HTTPConstants.AUTO_RELEASE_CONNECTION to true<br />serviceClient.getOptions().setProperty(HTTPConstants.AUTO_RELEASE_CONNECTION, Constants.VALUE_TRUE);<br />this would build the response stream once the response stream returned and release the connection. But this may have a performance hit since it build the OM tree at transport level.<br />2.Clean up the transport after each call <br />serviceClient.cleanupTransport();<br /><br />However both the above methods can only invoke two requests at time since there is only two connections. Again this may cause problems with invoking slow services. This can be avoided by the following technique to increase the default number of connections.<br /><br />ConfigurationContext configurationContext = <br /> ConfigurationContextFactory.createConfigurationContextFromFileSystem( <br /> AXIS2_REPOSITORY_LOCATION, AXIS2_CLIENT_CONFIG_FILE); <br /><br /> MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager = new MultiThreadedHttpConnectionManager(); <br /><br /> HttpConnectionManagerParams params = new HttpConnectionManagerParams(); <br /> params.setDefaultMaxConnectionsPerHost(20); <br /> multiThreadedHttpConnectionManager.setParams(params); <br /> HttpClient httpClient = new HttpClient(multiThreadedHttpConnectionManager); <br /> configurationContext.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient); <br /><br />and call serviceClient.cleanupTransport(); after each service invocation.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com57tag:blogger.com,1999:blog-7771139035631272063.post-80129141265181127562010-01-15T23:10:00.000-08:002010-01-15T23:21:17.464-08:00Changing Axis2 application pathBy default Axis2 generates an context path as follows when deployed it in tomcat or other application server.<br /><br />http://localhost:8080/axis2/services/Version?wsdl<br /><br />but most of the it is requried to customize this as follows.<br /><br />http://localhost:8080/myApp/myServices/Version?wsdl<br /><br />Below steps can be used to achive this.<br />1. Rename the web app name axis2 to myApp<br />2. Uncomment and edit the servicePath parameter at the axis2.xml file<br /><parameter name="servicePath">myServices</parameter><br />3. Add the following entry to web.xml. Here we need to add this entry rather than chaing existing one since services part is hard coded in some places.<br /><br /> <servlet-mapping><br /> <servlet-name>AxisServlet</servlet-name><br /> <url-pattern>/myServices/*</url-pattern><br /> </servlet-mapping><br /><br />How to get a path like this?<br /><br />http://localhost:8080/myServices/Version?wsdl<br /><br />This can be done my making this application as ROOT app<br />1. change the myApp to ROOTAmila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com5tag:blogger.com,1999:blog-7771139035631272063.post-20905377346508135092010-01-07T03:37:00.000-08:002010-01-07T03:45:13.449-08:00WSO2 Data Services v2.2.0 releasedAxis2 lets users to develop web services from the java code. This can either be a POJO where users write the business logic first or a generated code with the WSDL. In whatever form real business logic retrieve data from the data store (most of the time a database) and update it.<br /><br />Therefore isn't it useful to publish the data stored in permanent storage straight away (I.e using some descriptor files) without doing any coding? <a href="http://wso2.org/projects/data-services-server/java">WSO2 Data services server</a> let users to publish data by just writing a descriptor file. Currently it can publish data stored in many forms. eg. Databases, text files, excel sheets, google docs etc..<br />Since <a href="http://wso2.org/projects/data-services-server/java">WSO2 Data services server</a> build on top of WSO2 carbon platform it inherit all the WS* features such as security, reliable messaging, addressing etc ..<br /><br />Following are some of the key features:<br /><br />- Multiple data source support - any relational database accessible via JDBC, CSV, Excel, JNDI bound data sources and Google Spreadsheets<br />- Web service and REST interfaces for data<br />- Customizable response format to match your next adaptor's input<br />- Support for large data sets with little to no impact to the server's memory usage<br />- Nested queries and federated response from multiple disparate data sources<br />- Role based content filtering<br />- Full support for WS-Security, WS-Trust, WS-Policy, WS-SecureConversation and XKMS<br />- Web based GUI wizard<br />- Multi transport support - send and receive your data in either HTTP(s), SMTP, JMS and XMPP<br />- Reliable delivery of data<br />- Access throttling based on IP/Domain or frequency<br /><br />WSO2 Data Services 2.2.0 can be downloaded from <a href="http://wso2.org/downloads/data-services-server">http://wso2.org/downloads/data-services-server</a>.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com1tag:blogger.com,1999:blog-7771139035631272063.post-53297669256620043852010-01-01T07:44:00.000-08:002010-01-01T07:48:10.268-08:00Axis2 AuthenticationThe servlet specification provides four authentication mechanisms for any web application. Therefore any web services engine which receives http requests through a servlet can use those authentication mechanisms. Here is how you can do BASIC and DIGEST authentication with Apache Axis2 deployed under tomcat. <br /><br />Axis2 war distribution is a standard web application. This war distribution contains a web.xml and within it there is a servlet called AxisServlet which is used to receive the http requests.<br /><br />Configuring the war distribution.<br />First the following should add to the web.xml file to protect the AxisServlet from the anonymous access.<br /><br /><login-config><br /> <!-- <auth-method>BASIC</auth-method> --><br /> <auth-method>DIGEST</auth-method><br /> <realm-name>default</realm-name><br /></login-config><br /><br /><security-constraint><br /><web-resource-collection><br /> <web-resource-name>Protected Resource</web-resource-name><br /> <url-pattern>/services/*</url-pattern><br /></web-resource-collection><br /><br /><auth-constraint><br /> <role-name>tomcat</role-name><br /></auth-constraint><br /></security-constraint><br /><br />then add the following to the tomcat-users.xml<br /><user username="tomcat" password="tomcat" roles="tomcat"/><br /><br /><br />Now the servlet is protected and Lets see how to provide the credentials when accessing the service. This is in fact done by using the functionality available with the commons http client.<br /><br />ServiceClient serviceClient = new ServiceClient();<br /> serviceClient.setTargetEPR(new EndpointReference("http://localhost:8080/axis2/services/Version/getVersion"));<br /> serviceClient.getOptions().setAction("urn:getVersion");<br /><br /> HttpTransportProperties.Authenticator authenticator = new HttpTransportProperties.Authenticator();<br /> authenticator.setUsername("tomcat");<br /> authenticator.setPassword("tomcat");<br /><br /> serviceClient.getOptions().setProperty(HTTPConstants.AUTHENTICATE, authenticator);<br /> serviceClient.sendReceive(null);<br /> <br />This request can be send through a tcpmon to understand how this authentication works. First Axis2 client sends a normal request and tomcat server returns an Unauthorized response with the required authentication method.<br /><br />HTTP/1.1 401 Unauthorized<br /><br />Server: Apache-Coyote/1.1<br /><br />WWW-Authenticate: Digest realm="default", qop="auth", nonce="6da725c4d901eee87d2ad49cadbac74a", opaque="37629e27fec9bfaf38063bc3ab65f12d"<br /><br /><br />After receiving this Axis2 client sends another request with the authentication details.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com2tag:blogger.com,1999:blog-7771139035631272063.post-90435973546582466552009-11-30T01:08:00.000-08:002009-11-30T01:18:44.069-08:00Minimal jars required for Axis2 1.5Minimal jars required for Axis2 1.5 is slightly different from Axis2 1.4.1.<br /><br />Here is a set of jars required with Axis2 1.5 to invoke a service written using Axiom and<br />to invoke it using direct service client using default axis2.xml file.<br /><br />axis2-kernel-1.5.jar<br />axiom-api-1.2.8.jar<br />axiom-dom-1.2.8.jar<br />axiom-impl-1.2.8.jar<br />commons-logging-1.1.1.jar<br />wsdl4j-1.6.2.jar<br />XmlSchema-1.4.3.jar<br />neethi-2.0.4.jar<br />axis2-transport-local-1.5.jar<br />axis2-transport-http-1.5.jar<br />commons-httpclient-3.1.jar<br />mail-1.4.jar<br />commons-fileupload-1.2.jar<br />woden-api-1.0M8.jar<br />woden-impl-dom-1.0M8.jar<br />httpcore-4.0.jar<br />commons-codec-1.3.jar<br />geronimo-stax-api_1.0_spec-1.0.1.jar<br />wstx-asl-3.2.4.jar<br /><br /><br />axis2-jaxws-1.5.jar may be used to avoid some waning messages with the default axis2.xml.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com4tag:blogger.com,1999:blog-7771139035631272063.post-90836968446223972362009-10-05T06:30:00.001-07:002009-10-05T06:30:54.036-07:00Axis2 Class loadingAxis2 let users to deploy services and modules as separate archive files. These files can contain normal java classes or .jar files. Therefore at the deployment time Axis2 has to read those java classes and .jar files and create class loaders for services and modules. These are the places it looks for load those classes.<br />When axis2 deployed as web application using the axis2 war distribution, Axis2 uses the web application class loader (this contains WEB-INF/classes and WEB-INF/lib jars) as the top most parent.<br /><br />For service deployment it creates a service class loader using jars under the services/lib (this folder has to create by the users if needed) folder and using web application class loader as the parent. Then for each service it creates a separate class loader (which contains archive class files and lib jar files) using the service class loader as the parent.<br /><br />Similar thing happens for modules. The module class loader can uses the modules/lib folder to load the jar files and it use as the parent class loader for other modules. This forms the following parent child relationship for class loaders.<br /><br /> Web class loader<br /> services class loader modules class loader<br /> other service class loaders other service class loaders<br /><br />Child First (parent last) class loading<br />By default Axis2 uses the parent first class loading. Child first class loading can be switch by setting EnableChildFirstClassLoading parameter.<br /><parameter name="EnableChildFirstClassLoading">true</parameter><br /><br />Thread Context class loading<br />Some libraries uses the Thread context class loading. By default axis2 sets the service class loader as the thread context class loader before invoking a service. This can be changed by setting the context class loader to composite.<br /><br />I.e adding this parameter to service<br /><parameter name="ServiceTCCL">composite</parameter><br /><br />when this parameter is set it creates the context class loader by using both existing thread context class loader and service class loader.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com4tag:blogger.com,1999:blog-7771139035631272063.post-43035941803272312922009-10-01T08:12:00.000-07:002009-10-01T08:13:08.485-07:00Axis2 Hierarchical Service DeploymentAxis2 has a concept of a service archive (.aar). After introducing the custom deployers even users can deploy different types of files as services. (eg. .class and .jar for jaxws services).<br />But until recently all those service files had to kept in the services folder or respective other service folders. This may not efficient in managing a lot of services. With the introduction of hierarchical service deployment it is possible to keep the directory structure under the services folder and the folder structure is reflect in the service epr as well.<br /><br />eg. one can have services like this.<br /><br />./services/interop/rm/EchoStringService.aar<br /><br />./services/interop/rm/PingService.aar<br />./services/version/v1.1/version.aar<br /><br />./services/version/v1.2/version.aar<br /><br /><br />Epr for the PingService is <br />http://localhost:8080/axis2/services/interop/rm/PingService<br /><br />As seen in the last two lines this feature can be used for version management as well. Different version of the same service can be deployed and Epr is generated accordingly.<br /><br />http://localhost:8080/axis2/services/version/v1.2/VersionAmila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com3tag:blogger.com,1999:blog-7771139035631272063.post-31653774022134796102009-09-30T07:57:00.001-07:002009-09-30T07:58:13.468-07:00Inter operating Apache Sandesah2 with WCFRecently I have been working on interoperating WCF with the Apache Sandesha2. The good news is all the plain RM scenarios pass with some small fixings. Here is an sample client which can be used to invoke the wcf services available at http://131.107.72.15/endpoints/<br /><br />First I generated the code for the given wsdl with wsdl2java tool with the following arguments<br /><br />-uri http://10.100.1.238/ReliableMessaging_Service_WSAddressingAugust2004_Indigo/RequestReply.svc?wsdl<br /> -u -ap -uw<br /><br /> -p org.wso2.carbon.interop.microsoft.rm.requestreply<br /><br /> -o target/generated-code<br /><br /> -Emp org.wso2.carbon.interop.microsoft.rm.requestreply<br /><br /> -ns2p http://tempuri.org/=org.wso2.carbon.interop.microsoft.rm.requestreply,http://schemas.microsoft.com/2003/10/Serialization/=org.wso2.carbon.interop.microsoft.rm.requestreply.types<br /><br />Then we can simple invoke the service using the following client code.<br /><br />// creating an configuration context which contains sandesah2 and addressing<br /> ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem("target" + File.separator +<br /> "org.wso2.carbon.interop.microsoft.rm-SNAPSHOT.dir" +<br /> File.separator + "repository");<br /><br /> EchoStringServiceCustomBinding_IEchoString9Stub stub = new EchoStringServiceCustomBinding_IEchoString9Stub(configurationContext,<br /> "http://131.107.72.15/ReliableMessaging_Service_WSAddressingAugust2004_Indigo/RequestReply.svc/Reliable_Anonymous_Soap11_WSAddressingAugust2004_RM11");<br /> // this is to send messages through tcp mon<br /> stub._getServiceClient().getOptions().setProperty(Constants.Configuration.TRANSPORT_URL,<br /> "http://localhost:8088/ReliableMessaging_Service_WSAddressingAugust2004_Indigo/RequestReply.svc/Reliable_Anonymous_Soap11_WSAddressingAugust2004_RM11");<br /><br /> // setting the correct addressing , soap and rm versions<br /> stub._getServiceClient().getOptions().setProperty(AddressingConstants.WS_ADDRESSING_VERSION, AddressingConstants.Submission.WSA_NAMESPACE);<br /> stub._getServiceClient().getOptions().setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);<br /> stub._getServiceClient().getOptions().setProperty(SandeshaClientConstants.RM_SPEC_VERSION, Sandesha2Constants.SPEC_VERSIONS.v1_1);<br /><br /> //wcf does not support make connections so disable it<br /> Parameter sandeshaPolicyBeanParam = stub._getServiceClient().getAxisConfiguration().getParameter(Sandesha2Constants.SANDESHA_PROPERTY_BEAN);<br /> if (sandeshaPolicyBeanParam != null) {<br /> SandeshaPolicyBean sandeshaPolicyBean = (SandeshaPolicyBean) sandeshaPolicyBeanParam.getValue();<br /> sandeshaPolicyBean.setEnableMakeConnection(false);<br /> }<br /><br /> stub._getServiceClient().engageModule("addressing");<br /> stub._getServiceClient().engageModule("sandesha2");<br /><br /> PingRequestBodyType pingRequestBodyType = new PingRequestBodyType();<br /> pingRequestBodyType.setSequence("Sequence 1");<br /> pingRequestBodyType.setText("testparam");<br /> PingResponseBodyType pingResponseBodyType = null;<br /> String responseString = "";<br /> for (int i = 0; i < 3; i++) {<br /> responseString += "testparam";<br /> pingResponseBodyType = stub.echoString(pingRequestBodyType);<br /> }<br /><br /> // after sending the messages we can close and terminate the sequence<br /> SandeshaClient.closeSequence(stub._getServiceClient());<br /> SandeshaClient.terminateSequence(stub._getServiceClient());<br /><br /> //wait until terminate sequence messge is send<br /> SandeshaClient.waitUntilSequenceCompleted(stub._getServiceClient());Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com1tag:blogger.com,1999:blog-7771139035631272063.post-36435891948772435452009-09-27T22:40:00.000-07:002009-09-27T22:48:20.474-07:00Handling date and dateTime with Axis2With Axis2 1.5 java.util.Date is mapped to xs:date type and java.util.Calendar is mapped to xs:dateTime. For an example if we deployed a POJO service as follows<br /><br />public class TestService {<br /><br /> public Date getDate() {<br /> return new Date();<br /> }<br /><br /> public Calendar getCalendar() {<br /> return Calendar.getInstance();<br /> }<br />}<br /><br />This generates an WSDL with schema like this.<br /><br /><xs:element name="getDateResponse"><br /> <xs:complexType><br /> <xs:sequence><br /> <xs:element minOccurs="0" name="return" nillable="true" type="xs:date"/><br /> </xs:sequence><br /> </xs:complexType><br /></xs:element><br /><xs:element name="getCalendarResponse"><br /><xs:complexType><br /> <xs:sequence><br /> <xs:element minOccurs="0" name="return" nillable="true" type="xs:dateTime"/><br /> </xs:sequence><br /></xs:complexType><br /></xs:element><br />When invoking the service we get the following response xmls<br /><br /><ns:getDateResponse xmlns:ns="http://service.lockhead.test"><ns:return>2009-09-28</ns:return></ns:getDateResponse><br /><ns:getCalendarResponse xmlns:ns="http://service.lockhead.test"><ns:return>2009-09-28T10:55:01.770+05:30</ns:return></ns:getCalendarResponse>Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com3tag:blogger.com,1999:blog-7771139035631272063.post-69996267573419019322009-09-24T21:55:00.000-07:002009-09-24T21:59:39.660-07:00Sending an arbitrary soap message with Axis2Axis2 code generation strictly follows the WS-I profile which prohibits sending soap messages with two child elements in the soap body. Even normal Service client API allows only one omElement to be send at the soap body.<br />One work around to send two elements is to use an operation client which allows a user to set whole SoapEnvelope hence sending any arbitrary one.<br /><br /> ServiceClient serviceClient = new ServiceClient();<br /> OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);<br /> //creating message context<br /> MessageContext outMsgCtx = new MessageContext();<br /> Options opts = outMsgCtx.getOptions();<br /> //setting properties into option<br /> opts.setTo(new EndpointReference("http://localhost:8088/axis2/services/TestInOutService"));<br /> opts.setAction("urn:TestInOutService");<br /><br /> SOAPFactory soapFactory = OMAbstractFactory.getSOAP11Factory();<br /> SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();<br /><br /> OMElement omElement1 = soapFactory.createOMElement(new QName("http://axis2.test","firstElement"));<br /> OMElement omElement2 = soapFactory.createOMElement(new QName("http://axis2.test","secondElement"));<br /><br /> soapEnvelope.getBody().addChild(omElement1);<br /> soapEnvelope.getBody().addChild(omElement2);<br /><br /> outMsgCtx.setEnvelope(soapEnvelope);<br /> opClient.addMessageContext(outMsgCtx);<br /> opClient.execute(true);<br /><br /> MessageContext inMsgtCtx = opClient.getMessageContext("In");<br /><br /> SOAPEnvelope response = inMsgtCtx.getEnvelope();<br /> System.out.println(response);Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com5tag:blogger.com,1999:blog-7771139035631272063.post-6315002186770965132009-05-20T04:22:00.000-07:002009-05-20T04:23:39.238-07:00Axis2 child first class loadingWith axis2 it is possible to deploy services as service archive files and modules as module archive files. Both these two types of archives can contain .class or .jar files within it. Axis2 creates a separate class loader to load these class and jar files within the archive file.<br /> By default Axis2 uses parent first class loading. This means jvm search for a particular class in parent before search it at the current class loader. As a result of this user could not use a different version of a jar file within their archives. <br /> I recently added the child first class loading support (this is only available with main trunk) so that users can use different versions of class files at their services. <br /><br />How to enable it?<br /> This can be globally enable by setting the 'EnableChildFirstClassLoading' parameter to true at the axis2.xml file. Further the behavior of the services or modules can be set adding the same parameter to services.xml and module.xml.<br /><br />How it works?<br />Axis2 uses a custom class loader called DeploymentClassLoader which is extended from the java URLClassloader. URLClassloader uses a parent first approach. LoadClass method of the java classloader class looks like this,<br /><br />protected synchronized Class<?> loadClass(String name, boolean resolve)<br /> throws ClassNotFoundException<br /> {<br /> // First, check if the class has already been loaded<br /> Class c = findLoadedClass(name);<br /> if (c == null) {<br /> try {<br /> if (parent != null) {<br /> c = parent.loadClass(name, false);<br /> } else {<br /> c = findBootstrapClass0(name);<br /> }<br /> } catch (ClassNotFoundException e) {<br /> // If still not found, then invoke findClass in order<br /> // to find the class.<br /> c = findClass(name);<br /> }<br /> }<br /> if (resolve) {<br /> resolveClass(c);<br /> }<br /> return c;<br /> }<br /><br />it first checks the parent class loader to check the class and child class loader after that. We can revise this order simply overriding this method at the DeploymentClassLoader like this,<br />protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {<br /> Class c = null;<br /> if (!isChildFirstClassLoading) {<br /> c = super.loadClass(name, resolve);<br /> } else {<br /> c = findLoadedClass(name);<br /> if (c == null) {<br /> try {<br /> c = findClass(name);<br /> } catch (Exception e) {<br /> c = super.loadClass(name, resolve);<br /> }<br /> }<br /> }<br /> return c;<br /> }<br /><br />Here the isChildFirstClassLoading is set according to the parameters uses set above.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com3tag:blogger.com,1999:blog-7771139035631272063.post-10462349558088198382009-05-07T01:18:00.000-07:002009-05-07T01:19:54.638-07:00Improving Axis2 client http transport performanceAlthough Axis2 supports a many transports http is the highly used one. Axis2 uses Apache HttpClient to implement its http transports sender. By default Axis2 creates a new http client object per invocation. This causes a new MultiThreadedHttpConnectionManager object being created for each invocation. As a result axis2 by default does not use the http 1.1 keep alive feature as well.<br />The solution for this problem is to re use the same HttpClient and MultiThreadedHttpConnectionManager per one thread. Axis2 client invocation may happen using one thread or using multiple threads. After reusing the MultiThreadedHttpConnectionManager has to shut down to release connections. If not this can lead to multiple tcp CLOSE_WAIT connections situation.<br /><br />Following code shows this settings.<br /><br />// creates a new connection manager and a http client object<br />MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();<br /> HttpClient httpClient = new HttpClient(httpConnectionManager);<br /><br /> try {<br /><br /> client = new ServiceClient(null, null);<br /> Options opts = new Options();<br /> client.setOptions(opts);<br /> opts.setTo(new EndpointReference("http://localhost:8085/axis2/services/TestInOutService"));<br /> opts.setAction("urn:TestInOutService");<br /><br /> OMElement payload = buildSoapObject(<br /> "<ns1:getPrice xmlns:ns1=\"http://quickstart.samples/xsd\">" +<br /> "<ns1:symbol>IBM</ns1:symbol>" +<br /> "</ns1:getPrice>"<br /> );<br /> System.out.println("Sending the request ...." + System.currentTimeMillis());<br /><br /> <br /> // set the above created objects to re use.<br /> client.getOptions().setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);<br /> client.getOptions().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);<br /> <br /> // since we reuse the same http client and conneciton manager all these http messages<br /> // will go in one tcp connection.<br /> // this can be verified by sending the messages through tcpmon.<br /> for (int i = 0; i < 10; i++) {<br /> OMElement response = client.sendReceive(payload);<br /> response.build();<br /> }<br /> <br /><br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> }<br /> finally {<br /> if (client != null) {<br /> try {<br /> client.cleanupTransport();<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> }<br /><br /> try {<br /> client.cleanup();<br /> } catch (Exception e) {<br /> e.printStackTrace();<br /> }<br /> }<br /><br /> }<br /> try {<br /> Thread.sleep(1000);<br /> } catch (Exception e) {// do nothing}<br /> }<br /> httpConnectionManager.closeIdleConnections(0);<br /> httpConnectionManager.shutdown();Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com20tag:blogger.com,1999:blog-7771139035631272063.post-2604471962840557752009-02-16T20:32:00.000-08:002009-02-16T20:34:10.792-08:00Accessing WSO2 products back end directlyRecently wso2 release a set of products which address all aspects of any SOA solution. All these products are build upon a platform called WSO2 carbon which is base on OSGI. One of the common features of them is to ability to run as Front End (FE) and Back End (BE) services. FE server contains all the GUI components and BE server expose the back end functionality as web services. Therefore in a typical Adminconsole usage scenario client application runs on the browser makes servlet request to FE server and FE server makes a web service call to BE server.<br />As it can be seen it is possible to access these BE serer web services directly using web service clients generated using the respective WSDL files for the service. The following example code provides a code for such a client which try to directly access the WS02 registry back end services to put a resource and retrieve it back. Generally this code segment show how one can access a service using https transport and mange cookies between many stubs.<br /><br />try {<br /><br /> // set the system properties to enable the https conection<br /> System.setProperty("javax.net.ssl.trustStore", "src/test/resources/wso2carbon.jks");<br /> System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");<br /><br /> // first authenticate the client.<br /> AuthenticationAdminServiceStub authenticationStub =<br /> new AuthenticationAdminServiceStub("https://10.100.1.104:9443/services/AuthenticationAdminService");<br /> authenticationStub._getServiceClient().getOptions().setManageSession(true);<br /> boolean loggedIn = authenticationStub.login("admin", "admin", NetworkUtils.getLocalHostname());<br /><br /> // get the cooke to use in the next service invoations. This lets registry service to authenticate<br /> // the second request<br /> ServiceContext serviceContext = authenticationStub._getServiceClient().getLastOperationContext().getServiceContext();<br /> String sessionCookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);<br /> // print the cookie<br /> System.out.println("session Cookie " + sessionCookie);<br /><br /> // doing the registry update<br /> ResourceAdminServiceStub stub = new ResourceAdminServiceStub("https://10.100.1.104:9443/services/ResourceAdminService");<br /> stub._getServiceClient().getOptions().setManageSession(true);<br /> stub._getServiceClient().getOptions().setTimeOutInMilliSeconds(60000000);<br /> // create a path to add new resource<br /> String path = "/testfolder/axis2.zip";<br /> String mediaType = "application/xml";<br /> String description = "test service";<br /> // enable MTOM and set the previous cookie<br /> stub._getServiceClient().getOptions().setProperty(Constants.Configuration.ENABLE_MTOM, Constants.VALUE_TRUE);<br /> stub._getServiceClient().getOptions().setProperty(HTTPConstants.COOKIE_STRING, sessionCookie);<br /> DataHandler dataHandler = new DataHandler(new FileDataSource("/home/amila/services.xml"));<br /> // adding the resource<br /> stub.addResource(path, mediaType, description, dataHandler);<br /><br /> // getting content<br /> ContentDownloadBean contentDownloadBean = stub.getContentDownloadBean("/testfolder/testxml3");<br /> DataHandler response = contentDownloadBean.getContent();<br /> FileOutputStream fileOutputStream = new FileOutputStream("/home/amila/new_services2.xml");<br /> response.writeTo(fileOutputStream);<br /> fileOutputStream.flush();<br /> } catch (AxisFault axisFault) {<br /> axisFault.printStackTrace();<br /> } catch (java.rmi.RemoteException e) {<br /> e.printStackTrace();<br /> } catch (org.wso2.carbon.registry.mgt.ui.resource.services.ExceptionException0 exceptionException0) {<br /> exceptionException0.printStackTrace();<br /> } catch (org.wso2.carbon.core.services.authentication.AuthenticationExceptionException0 authenticationExceptionException0) {<br /> authenticationExceptionException0.printStackTrace();<br /> } catch (SocketException e) {<br /> e.printStackTrace();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com1tag:blogger.com,1999:blog-7771139035631272063.post-88905283821504679722009-01-03T18:48:00.000-08:002009-01-03T18:51:29.881-08:00Using MTOM with Axis2MTOM provides a way to send binary data as it is without encoding it to a text format. Axis2 ADB has built in support for MTOM. Therefore it is almost a trivial task to send and receive binary data using axis2.<br /><br />Here is an sample wsdl<br /><br /><definitions xmlns:tns="http//tempuri.org/sample"<br /> xmlns:ns1="http//tempuri.org/sample/types"<br /> xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"<br /> xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"<br /> xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br /> xmlns="http://schemas.xmlsoap.org/wsdl/"<br /> targetNamespace="http//tempuri.org/sample"><br /> <types><br /> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br /> xmlns:tns="http//tempuri.org/sample/types"<br /> targetNamespace="http//tempuri.org/sample/types"<br /> elementFormDefault="qualified"<br /> attributeFormDefault="unqualified"><br /> <xsd:element name="echoBinaryData"><br /> <xsd:complexType><br /> <xsd:sequence><br /> <xsd:element name="param" type="xsd:base64Binary"/><br /> </xsd:sequence><br /> </xsd:complexType><br /> </xsd:element><br /> <xsd:element name="echoBinaryDataResponse"><br /> <xsd:complexType><br /> <xsd:sequence><br /> <xsd:element name="param" type="xsd:base64Binary"/><br /> </xsd:sequence><br /> </xsd:complexType><br /> </xsd:element><br /> </xsd:schema><br /> </types><br /><br /> <message name="EchoBinaryDataRequest"><br /> <part name="part1" element="ns1:echoBinaryData"/><br /> </message><br /> <message name="EchoBinaryDataResponse"><br /> <part name="part1" element="ns1:echoBinaryDataResponse"/><br /> </message><br /><br /> <portType name="SamplePortType"><br /> <operation name="echoBinaryData"><br /> <input message="tns:EchoBinaryDataRequest"/><br /> <output message="tns:EchoBinaryDataResponse"/><br /> </operation><br /> </portType><br /><br /> <binding name="SampleSoap11Binding" type="tns:SamplePortType"><br /> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/><br /> <operation name="echoBinaryData"><br /> <soap:operation style="document" soapAction="urn:echoBinaryData"/><br /> <input><br /> <soap:body use="literal"/><br /> </input><br /> <output><br /> <soap:body use="literal"/><br /> </output><br /> </operation><br /> </binding><br /> <binding name="SampleSoap12Binding" type="tns:SamplePortType"><br /> <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/><br /> <operation name="echoBinaryData"><br /> <soap12:operation style="document" soapAction="urn:echoBinaryData"/><br /> <input><br /> <soap12:body use="literal"/><br /> </input><br /> <output><br /> <soap12:body use="literal"/><br /> </output><br /> </operation><br /> </binding><br /><br /> <service name="SampleService"><br /> <port name="Soap11Port" binding="tns:SampleSoap11Binding"><br /> <soap:address location="http://localhost:8080/axis2/services/SampleService"/><br /> </port><br /> <port name="Soap12Port" binding="tns:SampleSoap12Binding"><br /> <soap:address location="http://localhost:8080/axis2/services/SampleService"/><br /> </port><br /> </service><br /></definitions><br /><br />then both client and server side code can be generated with the wsdl2java tool.<br /><br />it sends and receives a binary file. Following client and server side code can be used to send and receive binary data.<br />try {<br /> SampleServiceStub stub = new SampleServiceStub("http://localhost:8080/axis2/services/SampleService");<br /> stub._getServiceClient().getOptions().setProperty(Constants.Configuration.ENABLE_MTOM, Constants.VALUE_TRUE);<br /> String clientFolder = "/home/amila/work/articles/binary/samples/mtom/client/";<br /> DataSource dataSource = new FileDataSource(clientFolder + "client.jar");<br /> DataHandler request = new DataHandler(dataSource);<br /> DataHandler response = stub.echoBinaryData(request);<br /> FileOutputStream fileOutputStream = new FileOutputStream(clientFolder + "server.jar");<br /> response.writeTo(fileOutputStream);<br /> fileOutputStream.flush();<br /> System.out.println("Saved the file to client folder");<br /> } catch (AxisFault axisFault) {<br /> axisFault.printStackTrace();<br /> } catch (java.rmi.RemoteException e) {<br /> e.printStackTrace();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /><br />Skelton code.<br />public javax.activation.DataHandler echoBinaryData<br /> (<br /> javax.activation.DataHandler param<br /> ) {<br /><br /> String serverFolder = "/home/amila/work/articles/binary/samples/mtom/server/";<br /> try {<br /> FileOutputStream fileOutputStream = new FileOutputStream(serverFolder + "client.jar");<br /> param.writeTo(fileOutputStream);<br /> fileOutputStream.flush();<br /> System.out.println("Saved the file to client.jar");<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /><br /> FileDataSource fileDataSource = new FileDataSource(serverFolder + "server.jar");<br /> DataHandler dataHandler = new DataHandler(fileDataSource);<br /> return dataHandler;<br /> }Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com7tag:blogger.com,1999:blog-7771139035631272063.post-408907665979237362008-12-25T03:45:00.000-08:002008-12-25T03:50:59.752-08:00WSO2 WSAS 3.0-beta2 Released<a href="http://wso2.org/downloads/wsas">WSO2 WSAS 3.0-beta2</a> is now available for public review.<br />WSO2 WSAS is the enterprise version of widely used Axis2. WSO2 WSAS users the Axis2 and related other projects (Rampart, Sandesha2) to provide the Soap Stack <a href="http://wso2.org/projects/wsas/java/features">functionality</a>. It is shipped with a well tested version of these components (eg. Axis2 with some bug fixed version of Axis2 1.4.1) while supporting essential monitoring and administrative <a href="http://wso2.org/projects/wsas/java/features">functionality</a>. It supports scalability and high availability for web services with an improved and well tested clustering implementation.<br />Based on <a href="http://wso2.org/projects/carbon">WSO2 Carbon</a> platform since version 3.0, It lets users even to add WSO2 ESB which is based on synapse and WSO2 Mashup functionalities with a minimal effort.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com0tag:blogger.com,1999:blog-7771139035631272063.post-22545428218282952862008-11-30T05:46:00.000-08:002008-11-30T05:51:39.356-08:00Low cost IT solutionsWith the global economic crisis a lot of companies find it difficult to mange their IT budgets with the commercial proprietary software products. Most of these companies find Open source software products as a solution for there problem. <br />This article named as <a href="http://wso2.com/about/news/open-source-lets-developers-speed-soa-development-despite-economic-slowdown/">Open source lets developers speed SOA development despite economic slowdown</a><br />describes how the company called <a href="http://www.concur.com">concur</a> have build there SOA solution using <a href="http://wso2.org/">WSO2</a> open source products.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com0tag:blogger.com,1999:blog-7771139035631272063.post-24989546367193807882008-11-30T04:59:00.000-08:002008-11-30T05:04:49.637-08:00Axis2 service InvocationsAxis2 client API provides a comprehensive set of ways to access a web service. In fact there are four ways depending on the following two properties.<br /><br />1.Synchronous/Asynchronous invocations – whether client thread wait until response comes or not<br />2.Single/Dual Channel invocations. - whether the response comes on the back channel or a separate channel initiated by the server.<br /><br />Now lets see each and every method separately.<br /><br /><span style="font-weight:bold;">1.Synchronous Single channel</span><br />In this way the client side invocation thread blocks until the response message comes. If the transport is Http it can be seen that the response comes at the back channel with Http status 200 ok. By default Axis2 works on the single channel mode. Therefore following method does the job. Note that this method returns the response.<br /><span style="font-style:italic;">serviceClient.sendReceive(getTestOMElement())</span><br /><br /><span style="font-weight:bold;">2.Asynchronous Single channel</span><br />Unlike in the earlier way this kind of invocation returns the client thread immediately. User should register a callback to get the response. But response comes in the back channel as in the earlier case. Following code can be used for this kind of invocation.<br /><br /> <span style="font-style:italic;">AxisCallback axisCallback = new AxisCallback() {<br /> public void onMessage(MessageContext msgContext) {<br /> System.out.println("Got the message ==> " + msgContext.getEnvelope().getBody().getFirstElement());<br /> }<br /><br /> public void onFault(MessageContext msgContext) {<br /><br /> }<br /><br /> public void onError(Exception e) {<br /> System.out.println("Received an error ...");<br /> }<br /><br /> public void onComplete() {<br /><br /> }<br /> };<br /> serviceClient.sendReceiveNonBlocking(getTestOMElement(), axisCallback);</span><br /><br /><span style="font-weight:bold;">3.Synchronous Dual channel mode</span><br />The only difference of this invocation compare to others is that the invocation happens using two different http channels. This type of invocation can only be done using Addressing. i.e both client and service should have addressing enabled. Before sending the request Axis2 client starts a Simple Http server at client side and set the Endpoint reference address of this server to the reply-To addressing header. The request channel receives a Http 202 Accepted header. Server reads the reply-to header from the request and starts a new channel to the reply-to header address. Here is the code for this.<br /><span style="font-style:italic;">serviceClient.engageModule("addressing")<br />serviceClient.getOptions().setUseSeparateListener(true);<br />serviceClient.sendReceive(getTestOMElement());</span><br /> <br /> The useSeparateListener attribute is used to specify this dual channel mode.<br /><br /><span style="font-weight:bold;">4.Asynchronous Dual channel mode</span><br />This is the complete asynchronous invocation method. Client immediately returns the thread and response message receive in a separate channel. This kind of access can be made by adding the addressing engaging and useSeperateListner code for the second type of invocation.<br /><br /> <span style="font-style:italic;">AxisCallback axisCallback = new AxisCallback() {<br /> public void onMessage(MessageContext msgContext) {<br /> System.out.println("Got the message ==> " + msgContext.getEnvelope().getBody().getFirstElement());<br /> }<br /><br /> public void onFault(MessageContext msgContext) {<br /><br /> }<br /><br /> public void onError(Exception e) {<br /> e.printStackTrace();<br /> System.out.println("Received an error ...");<br /> }<br /><br /> public void onComplete() {<br /><br /> }<br /> };<br /> serviceClient.engageModule("addressing")<br /> serviceClient.getOptions().setUseSeparateListener(true);<br /> serviceClient.sendReceiveNonBlocking(getTestOMElement(), axisCallback);</span>Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com0tag:blogger.com,1999:blog-7771139035631272063.post-30655326790104301012008-11-13T22:30:00.000-08:002008-11-13T22:43:11.315-08:00Getting java runtime stack traceIn most of the time finding java runtime stack trace is useful in debugging. The common practice is to run the application in debug mode and find the stack trace.<br />Here is a way I found to print the stack trace within the java code it self without running in debug mode. I found this in JavaUtils class of the Axis2 kernel.<br /><br /> public static String callStackToString() {<br /> return stackToString(new RuntimeException());<br /> }<br /><br /> public static String stackToString(Throwable e) {<br /> java.io.StringWriter sw = new java.io.StringWriter();<br /> java.io.BufferedWriter bw = new java.io.BufferedWriter(sw);<br /> java.io.PrintWriter pw = new java.io.PrintWriter(bw);<br /> e.printStackTrace(pw);<br /> pw.close();<br /> String text = sw.getBuffer().toString();<br /> // Jump past the throwable<br /> text = text.substring(text.indexOf("at"));<br /> text = replace(text, "at ", "DEBUG_FRAME = ");<br /> return text;<br /> }Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com0tag:blogger.com,1999:blog-7771139035631272063.post-9110363451884580512008-11-05T22:50:00.000-08:002008-11-05T22:52:25.219-08:00Accessing Axis2 Information at Client and ServiceMost of the people get used to implement web services either using POJO or generated services with wsdl using wsdl2java tool. The preferred way to generate the client code is again to use wsdl2java tool with service wsdl. In other words people preferred to use data bound java classes. <br />But sometimes they need to get inside information even at the Client and service level. Axis2 internally keep XML data as an Axiom object. It uses the context hierarchy in processing data. For each message Axis2 creates a message context which is bound to an Operation Context. Normally an Operation Context can have one or two message contexts depending on the Operation MEP (message exchange pattern). Therefore if there is a way to get access to Message Context or Operation Context all these details can be retrieved by using them.<br /><br /><span style="font-weight:bold;">At server side.</span><br />At the server side message context can be accessed like this,<br />MessageContext messageContext = MessageContext.getCurrentMessageContext(); <br /><br />once get the message context then any thing can be access from that <br />messageContext.getEnvelope(); // getting soap envelop<br /> messageContext.getProperties(); // getting all the properties these inclued properties set by transports as well<br /> messageContext.getOperationContext(); // accessing operation context<br /> messageContext.getAxisOperation(); // axis operation information<br /> messageContext.getAxisService(); // axis servier information <br /><br /><span style="font-weight:bold;">At the client side.</span> <br />At the client side operation context can be accessed like this,<br />OperationContext operationContext = stub._getServiceClient().getLastOperationContext();<br /> MessageContext outMessageContext = operationContext.getMessageContext(WSDL2Constants.MESSAGE_LABEL_OUT);<br /> MessageContext inMessageContext = operationContext.getMessageContext(WSDL2Constants.MESSAGE_LABEL_IN);<br /><br />Once got the message context other can be accessed as given above.Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com11tag:blogger.com,1999:blog-7771139035631272063.post-34000093229466312202008-11-03T23:07:00.000-08:002008-11-04T00:03:44.501-08:00Minimal jars to run Apache Axis2Apache Axis2 distributions comes with number of jars which are used in various services. Out of these 60 jar files there are only a few needs for some applications. Actually the minimum set of jars depends on the service type to be used.<br /><br />Here is a list of jars required to Deploy a service created by using wsdl2java tool using ADB databinding. This jars set is taken from Axis2 1.4.1 release.<br /><br />axis2-kernel-1.4.1.jar<br />commons-logging-1.1.1.jar<br />geronimo-stax-api_1.0_spec-1.0.1.jar<br />wstx-asl-3.2.4.jar<br />wsdl4j-1.6.2.jar<br />XmlSchema-1.4.2.jar<br />axiom-impl-1.2.7.jar<br />axiom-dom-1.2.7.jar<br />axiom-api-1.2.7.jar<br />backport-util-concurrent-3.1.jar<br />neethi-2.0.4.jar<br />commons-httpclient-3.1.jar<br />activation-1.1.jar<br />commons-fileupload-1.2.jar<br />woden-api-1.0M8.jar<br />woden-impl-dom-1.0M8.jar<br />httpcore-4.0-beta1.jar<br />axis2-adb-1.4.1.jar<br />commons-codec-1.3.jar<br /><br />For additional binding corresponding runtime jars for that binding is required. (i.e for xmlbeans-2.3.0.jar)Amila Suriarachchihttp://www.blogger.com/profile/15162735185293537609noreply@blogger.com7