Monday, 20 July 2009

Oracle Thin JDBC with tnsnames

Today I had to change my java project in a way that it uses Tnsnames for database resolving instead of a jdbc-url.

I googled around and found my answer here. This solution works with the jdbc-drivers from Oracle 10.2 onwards.

The solution basically is that you set the java system property "TNS_ADMIN". This can be done in two ways:
  1. By giving it as a java command line paramater: -Doracle.net.tns_admin=<tns_admin_home> eg.-Doracle.net.tns_admin=c:\\oracle\\OracleXE\\app\\oracle\\product\\10.2.0\\server\\NETWORK\\ADMIN
  2. Or setting from the code with the statement: System.setProperty("oracle.net.tns_admin", "<tns_admin_home>");

Example for the second option:
public final static String ORA_NET_TNS_ADMIN = "oracle.net.tns_admin";
...
// fetch tnsAdmin from a property file. Here hard-coded as an example:
public String tnsAdmin = "c:\\oracle\\OracleXE\\app\\oracle\\product\\10.2.0\\server\\NETWORK\\ADMIN";
...
System.setProperty(ORA_NET_TNS_ADMIN,tnsAdmin);
For an XE database for example the jdbc-url will be: jdbc:oracle:thin:@xe

The TNS_ADMIN property has to be set with the location/folder where the tnsnames.ora can be found. Not with the full-path to the tnsnames.ora.
I tried this with the database drivers from jdeveloper10.1.3.4 (ojdbc14.jar). But apparently they are from the 10.1 era. It does work with the one delivered with SqlDeveloper 1.5.x (ojdbc5.jar).

Thursday, 16 July 2009

Download Oracle Forms 11g Software

This day I decided to install Oracle Forms 11G on my laptop. First step:
Download the software. Usually this is the easiest part. Just go to otn
go to Developer Tools and choose traditional tools.



Following a few links I got to the following page:


So far so good. Normally I would get suspicious (Fusion Middleware??) but the phrase (contains forms 11.1.1.) gave me confidence.
Next page:



Now I was confused. In my opnion Oracle Forms is a development tool, but the For Development section says: Jdeveloper+ADF. Where can I download Oracle Forms? As there was only one valid option (forms is not for deployment ?) I decided to download and install

Oracle JDeveloper 11g Rel 1 (11.1.1.1.0) (JDeveloper + ADF)

After download and install I got exactly what Oracle said I would get: Jdeveloper + ADF. No Oracle Forms. (Afterwards this was ok, I had not installed Jdeveloper11g yet)
After some surfing on OTN I could not found another download area with Oracle Forms so I decided to navigate back to the fusion middleware page. Finally I decided to push the download button in the For Deployment section and to my big surprise there was a link to download Oracle Forms:




UPDATE:
I probably was not the only one that could not find the software. See Jan Carlin's blog:

http://groundside.com/blog/JanCarlin.php?title=finding_oracle_forms_on_otn_1&more=1&c=1&tb=1&pb=1

Monday, 13 July 2009

SoaSuite 11g Launched

Last Friday (july 10th) I went to the Fusion Middleware 11g introduction in De Meern, the Netherlands. Unfortunately I must say it was a bit of a bummer. I changed workingdays with my wife, since I found it a major introduction. At least partly due to all the recent acquisitions and forthcoming integrations, expecially with the nice BEA "gadgets", we've waited for 2 years, I think.
So I expected a huge party, with lots of drinks, cakes, decorations, nice gadgets, good speeches, in-depth tech demos and good-looking girls.
Well ok, it's a world-wide recession. And I know that Oracle is saving all their money to buy nice "new" companies to help us better. So that's for all the drinks, cakes, decorations, nice gatdgets and good-looking girls. Leaves us with the good speeches and in-depth tech demos, I mean the ones with the features we did not see allready in the previews.
Well the morning speeches were pretty ok, for executive briefings they might be considered good. Allthough quite some time was spent explaining that the demo's were actually pre-recorded flash-demo's. With the guarantee that it was recorded with real live production software.
But unfortunately the afternoon demo's were done by a very good guy, I'm sure, but he did not know much more about SoaSuite then the demo's and slides he studied.

So I did some digging up myself. That is, I was provided with some info by some good contacts, and I did some reading between the lines.
Most of the stuff about BPEL, Mediator, OSB, you probably allready know or have seen using the previews. I think people like Marc Kelderman and Lucas Jellema, can tell better than me.

But what pretty much is snowed under, are the B2B-capabilities or e-Commerce. Where Oracle's Integration B2B in 10g was a separate product, running on a 10gR2 app-server, B2B 11g is integrated with SoaSuite 11g.
As I can see it (I haven't had the change to to play with it), B2B is now sort of a binding in SoaSuite. This means that in stead of having to enqueue and dequeue messages on an AQ queue to have them transported with B2B, you can now couple your message-exchanges with Mediator.
Everything is tied together with a so-called Execution Context ID, so also B2B message-exchanges. And that's pretty neat since you can now track down a whole message change from B2b, via Mediator to BPEL PM and back. Since in 10g it was a seperate product, you had to correlate B2B messages to BPEL Processes yourself. We used to do that by putting the B2B-message-id on one of the BPEL PM indices.

The UI got a facelift too, getting it inline with the other AS consoles. Alltough in the demo's friday it occurred to me that the UI of Enterprise Manager/GridControl is stiil the same as the "old" AS UI's. B2B looks like Oracle ESB 10g, and FMW AS Control looks like the Weblogic consoles. So I think there is some work to do getting all the consoles in-line.

I got experienced with Integration B2B using the ebXML adapter. I got to know this one pretty in-depth. And I think ebXML is a very powerfull protocol. I have on my wishlist to create a HelloWorld E2E message flow with SoaSuite including ebXML between two machines.
One of the features on the wishlist was a CPA/CPP import/export utility. CPP stands for Collaboration Protocol Profile, which is an XML document that describes the ebXML capabilities of a partner. CPA is Collaboration Protocal Agreement and it describes the the parts of the CPP that two partners use with eachother: which message exchanges are allowed/agreed between two trading partners. I'm asured that these capabilities are upcoming (I hope I don't dissapoint my sources). That's also good news because this makes the configuration of B2B a lot easier.
Just import a CPA and you should be pretty much done. I expect only to have to deploy the agreement.

Another thing that caught my eye in the roadmaps is that in the upcoming releases B2B/eCommerce is included in AIA PIP's.

So although the dissapointing event of friday, I'm looking forward to be able to spare some time playing with SoaSuite 11g.

Tuesday, 7 July 2009

Jdeveloper 10.1.3.4 under 64-bit OpenSuse 11.1

Recently I upgraded my laptop to OpenSuse 11.1. I'm running the 64 bit (x86_64) variant of the distribution. So I had to install jDeveloper again. It's one of the few Oracle tools, besides SqlDeveloper that I don't run in a VM, but directly on the host. This is simple: installing jDeveloper is not much more than unzipping the archive.

Since it's out for a while, and I also upgraded my SoaSuite to 10.1.3.4, I tried the 10.1.3.4 jDeveloper. And where 10.1.3.3 runs smoothly on 64-bit linux, jDeveloper 10.1.3.4 won't. It complaints about having the wrong version of Java Hotspot or not being able to determine the right version.

I've search around for quite sometime, but yesterday I found a solution here.Thanks Nghiem. He wrote it for Ubuntu 8.10 X86_64, but it applies to every Linux X86_64. But at least OpenSuse 11.1.

What you need to do is to edit the jdev.conf, which you can find at <jdev_home>/jdev/bin/jdev.conf.

There you have to set the Java home, which has to be 64-bit:
#
# Directive SetJavaHome is not required by default, except for the base
# install, since the launcher will determine the JAVA_HOME. On Windows
# it looks in ..\..\jdk, on UNIX it looks in the PATH by default.
#
SetJavaHome /usr/lib64/jvm/java-1.5.0


Mark that jDeveloper is certified only for Java 1.5.

Then you have to unset the HotSpot (Java-Client) usage, by unsetting the SetJavaVM option:
#
# The Windows launcher will attempt to use client (hotspot) by default,
# unless a VM is specified below with the following directive. On UNIX
# we use whatever is listed first in the $(JAVA_HOME)/jre/lib/jvm.cfg file.
#
#SetJavaVM hotspot

After that running the jdev script in the <jdev_home>/jdev/bin folder will bring up jDeveloper 10.1.3.4.

According to Nghiem you can run into the problem of having a blank screen at startup. He suggested that it has something to do with a bug in his Java 1.5 version, that should be solved in Java 1.6 update 10. I did not run into that problem. But he solved it with adding the following line to the jdev startup script:
export AWT_TOOLKIT=MToolkit

Add it as the first line in the script (actually the second line, since the first comment-line is about denoting the shell). Save it and run it. I added it to try, but it broke my startup. So I uncommented it again. For me it worked without it.

Last week SoaSuite 11g is introduced. Next friday I go to the introduction event for Oracle partners. But SoaSuite 10.1.3 is used by many customers and I take it that most of them won't upgrade in short notice. Most SoaSuite trajects already run for quite a while and adding new functionality has higher priority than upgrading to the new release. And SoaSuite 10.1.3 has become a quite mature Soa environment. So I think it will be around for quite a while, so this tip might also be usefull for some time.

Monday, 6 July 2009

Logging and Properties in Weblogic

I was busy with developing a webservice to be deployed on Websphere. In fact it is the same service that brought me to get introduced in Sun's Metro & Glassfish. It's going to get a list of tasks for a user out of BPM Suite. So maybe I write an article soon about that too.

About deploying a Metro-webservice to Weblogic I wrote this article. But the webservice needs a configuration file with properties related to connecting to BPM-Suite. And I use log4j as a logging framework and it would be helpfull to see my webservice's logging in Weblogic too.

Properties
For getting the property file read within weblogic there are several options. But the best one is to get it loaded from the classpath. Having it loaded as a FileInputStream is not handy, because you need an absolute or relative path to the file. Absolute is not handy because puts strict constraints on the location of the file. A relative path is better, but with a application server you probably don't know from which base-folder it is started. So a classpath location is better. I used a propertyloader that is described here.
It turns out that root folder of the Weblogic domain you're running is a proper place to locate your property file. But you could extend the classpath with the domain's-config folder.
Changing the classpath can be done in the setDomainEnv.cmd (Windows) or setDomainEnv.sh (Unix/Linux) scripts. Look for "SET THE CLASSPATH". The classpath is build up from different pieces. You can edit the pieces earlier in the script or the classpath setting itsself, depending on what you find the proper place.

Log4J
Weblogic 10.3 by default makes use of JDK based logging. To use Log4J you need to do several steps:
  • Add log4j libraries: put the log4j-1.2.15.jar (got it from an Apache Axis distribution, but you can also download it directly from Apache) in the *weblogic-domain-home*/lib folder.
  • Add weblogic wllog4j.jar from *weblogic-server-home*\server\lib\ to the *weblogic-domain-home*/lib folder. (otherwise you get the error: java.lang.ClassNotFoundException: weblogic.logging.log4j.JDKLog4jAdapterFactory
  • Set log4j-logging in Weblogic, following this doc.
  • You can also add the property -Dweblogic.log.Log4jLoggingEnabled=true to the 'set JAVA_PROPERTIES' line in the setDomainEnv script.
  • Then you might want to have your own log4j.properties file loaded. That is possible by setting the environment variable LOG4J_CONFIG_FILE to the location of your property file.
Restart your weblogic domain to get the settings effective. w

Tuesday, 30 June 2009

The Char: Myth busted or confirmed?

There are many myths on the Oracle database. Many of those myths were true statements versions ago, but became myths because the Oracle database developers outsmarted the limitations. There was a myth that said that you should put non-null columns in the beginning of the table and null columns at the end. This was because in earlier versions a null column in a row did not take space until there was a filled column after it. In that case the database preallocated space for the null column to save on re-allocation efforts. But I learned that the storing-techniques of the database were improved in a way that this statement became a myth. Although it is still a good practice to have a standard on organizing your tables.

I know quite a lot of the Oracle database. But most of it is from using the modern ones and carrying the lugage of courses in the older ones. I know how a car and it's engine theoretically work, but I have no up-to-date knowlegde of the internals of the modern car. In the same way I have to rely on what I hear from other experts and co-workers about statements as above. So I keep my ears open and carefull about spreading myths.

This week a valued co-worker came with a DDL-script to create a table with Char-columns. My first reaction was that he should replace the CHARs with VARCHAR2s. Since a Varchar, as suggested by it's name, should occupy space related to it's fillings, while a CHAR occupies space according to it's maximum size. Though this was true, I was not sure if this statement was passed over by the reality of the modern database's storage techniques.
But according to Tom Kyte, the statement still holds (article started in 2001, but is updated recently). However, browsing to the end of the article's list of comments, I read: if a char or a varchar2 column is null, than it does not take more room then is needed to hold the null-value.

So myth confirmed...

Monday, 15 June 2009

Hello Metro


Developing Hello World with Eclipse

In my previous article I wrote about installing Metro and Glassfish. That article is the prelude for this one. Developing webservices using a toolstack like Metro (as alternative for Apache Axis for example) opposed to developing them in your Application Servers native technology gives you more flexibility in choosing your deployment target. You may rightfully respond with stating that Metro is the native technology of Sun's Glassfish Application Server. It is in fact part of it. But Metro is also available as a separate library for other Application Servers or even standalone clients.

The basics of developing a webservice using Metro in Eclipse is written at: https://metro.dev.java.net/guide/Developing_with_Eclipse.html.

When having your workspace on a network share, define a drive-letter for it or a mount point (for example: /home/makker/workspace) and don’t use the windows-network-path reference (\\networkhost\Share$\makker). Otherwise deployment may fail because of ‘file not found errors’.

A HelloWorld webservice using Metro in Eclipse is really simple.
1. Create a new dynamic Web Project:
2.Name it HelloWorldWS and choose Glassfish as target runtime:and choose Next:

3. Specify the context Root (For example HelloWorldWS):

4. And click Finish.
5. Then create a HelloWorld java Class, from the new-gallery:

6.Implement the following code:
package com.hello.sample;
import javax.jws.WebService;
@WebService(name="HelloWorldWS", serviceName="HelloWorldWS")
public class HelloWorld {
public String hello(String name){
return "Hello "+name;
}
}
It’s all about the WebService annotation really.
7. Go to your GlassFish server in the Servers tab and right click -> ‘Add and Remove Projects’. Shuttle your HelloWorld project to the right.

8. Click Finish. The project will be synchronized with the server automatically. If you do a change then with Right Click>Publish you can synchronize again.
9. The wsdl will be on: http://localhost:8080/HelloWorld/HelloWorldWS?wsdl
10. This can be tested with SoapUI.

Create a HelloWorld Webservice using Ant

The same project can be created using ANT. This is especially usefull when the source may change during development. And when deploying to a another AS then Glassfish.

To generate the necessary webservice code from java-source (bottom-up), APT (Annotation Processor Tool) is used. For Apt an Ant task exist.
For starting your project from WSDL (top-down) also API's and corresponding Ant taks are available. With Metro samples are delivered to show how to do that.

Again create a Dynamic Web Project, like above.
Then create a build.xml script like:

 <?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="help" name="HelloWorld">
<!-- ********** Imports ********** -->
<!-- import base settings -->
<import file="etc/config.xml"/>
<!-- Set jaxws-Class Path -->
<path id="jaxws.classpath">
<pathelement location="${java.home}/../lib/tools.jar"/>
<fileset dir="${metro.lib.home}">
<include name="*.jar"/>
<exclude name="j2ee.jar"/>
</fileset>
</path>
<!-- ********** Task Defs ********** -->
<!-- Import Apt Task Def based on jaxws-classpath -->
<taskdef name="apt" classname="com.sun.tools.ws.ant.Apt">
<classpath refid="jaxws.classpath"/>
</taskdef>
<!-- clean -->
<target name="clean">
<delete dir="${build.home}" includeEmptyDirs="true"/>
<delete dir="${wsdl.home}"/>
<delete file="${webcontent.webinf.home}/sun-jaxws.xml"/>
<delete file="${webcontent.webinf.home}/web.xml"/>
</target>
<!-- Targets -->
<target name="setup">
<mkdir dir="${build.home}"/>
<mkdir dir="${build.classes.home}"/>
<mkdir dir="${webcontent.home}"/>
<mkdir dir="${webcontent.webinf.home}"/>
<!--   <mkdir dir="${wsdl.home}"/>-->
</target>
<!-- Build webservice based on Java-Source -->
<target name="build-server-java" depends="setup">
<echo message="Apt: Generate WebService"/>
<apt
   fork="true"
   debug="true"
   verbose="${verbose}"
   destdir="${build.classes.home}"
   sourcedestdir="${basedir}/src"
   sourcepath="${basedir}/src">
<classpath>
   <path refid="jaxws.classpath"/>
   <pathelement location="${basedir}/src"/>
</classpath>
<option key="r" value="${build.home}"/>
<source dir="${basedir}/src">
   <include name="**/com/rabo/samples/*.java"/>
</source>
</apt>
<echo message="Copy: Jaxws Deployment Descriptor"/>
<!--  copy jaxws deployment descriptors -->
<copy todir="${webcontent.webinf.home}">
<fileset dir="${basedir}/etc/deployment">
   <include name="sun-jaxws.xml"/>
</fileset>
</copy>
</target>
<!-- Help! (default)  -->
<target name="help">
<!--        <echo message="AS_HOME:            ${as.home}"/>-->
<echo message="Settings:"/>
<echo message="METRO_HOME:        ${metro.home}"/>
<echo message=""/>
<echo message="Targets:"/>
<echo message="server:            Generate & build webservice"/>
</target>
<!-- Generate and Build the webservice -->
<target name="server" depends="setup">
<antcall target="clean"/>
<antcall target="build-server-java"/>
</target>

</project>


It expects a config.xml file in the *project*/etc folder:

<project>
<!-- Environment Variables -->
<property environment="env"/>
<!-- Application Server Home (env var AS_HOME must be set) -->
<property name="as.home" value="${env.AS_HOME}"/>
<!-- Metro Home (env var METRO_HOME must be set) -->
<property name="metro.home" value="${env.METRO_HOME}"/>
<property name="metro.lib.home" value="${metro.home}/lib"/>
<property name="source.home" value="${basedir}/src"/>
<property name="build.home" value="${basedir}/build"/>
<property name="build.classes.home" value="${build.home}/classes"/>
<property name="webcontent.home" value="${basedir}/WebContent"/>
<property name="webcontent.webinf.home" value="${webcontent.home}/WEB-INF"/>
<property name="wsdl.home" value="${webcontent.webinf.home}/wsdl"/>
</project>


The scripts expect JAVA_HOME and METRO_HOME to be set.
Create the same java class as in the former example:
package com.hello.sample;
import javax.jws.WebService;
@WebService(name="HelloWorldWSAnt", serviceName="HelloWorldWSAnt")
public class HelloWorld {
public String hello(String name){
return "Hello "+name+"! Used Ant to generate this.";
}
}

This time I changed the name and the service name to distinguish from the former example.
To generate the webservice code perform:
ant server

The ant script also places a web.xml, and a sun-jaxws.xml into the WebContent/WEB_INF folder. It expects these files in the /etc/deployment folder.
The sun-jaxws.xml file should look like:
<?xml version="1.0" encoding="UTF-8"?>

<!--
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.

Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.

The contents of this file are subject to the terms of either the GNU
General Public License Version 2 only ("GPL") or the Common Development
and Distribution License("CDDL") (collectively, the "License").  You
may not use this file except in compliance with the License. You can obtain
a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
language governing permissions and limitations under the License.

When distributing the software, include this License Header Notice in each
file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
Sun designates this particular file as subject to the "Classpath" exception
as provided by Sun in the GPL Version 2 section of the License file that
accompanied this code.  If applicable, add the following below the License
Header, with the fields enclosed by brackets [] replaced by your own
identifying information: "Portions Copyrighted [year]
[name of copyright owner]"

Contributor(s):

If you wish your version of this file to be governed by only the CDDL or
only the GPL Version 2, indicate your decision by adding "[Contributor]
elects to include this software in this distribution under the [CDDL or GPL
Version 2] license."  If you don't indicate a single choice of license, a
recipient has the option to distribute your version of this file under
either the CDDL, the GPL Version 2 or to extend the choice of license to
its licensees as provided above.  However, if you add GPL Version 2 code
and therefore, elected the GPL Version 2 license, then the option applies
only if the new code is made subject to such option by the copyright
holder.
-->

<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
<endpoint
name='HelloWorldWSAnt'
implementation='com.rabo.samples.HelloWorld'
url-pattern='/HelloWorldWSAnt'/>
</endpoints>

It’s in fact the deployment file for Metro. For deployment on Glassfish this is enough. Apparently deploying to Glassfish from Eclipse would not need this file.
For deployment to a non-glassfish application server (like Weblogic), you would also need a valid Web.xml. This file should look like:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>HelloWorldWSAnt</display-name>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>HelloWorldWSAnt</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldWSAnt</servlet-name>
<url-pattern>/HelloWorldWSAnt</url-pattern>
</servlet-mapping>
<session-config>
 <session-timeout>60</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>


This Web-deployment file is generated when deploying to Glassfish from Eclipse. So don’t use this file in the WEB_INF folder in the Glassfish case. The web.xml will then be generated. The generated web.xml file will point to a JAXWSServlet class in the Glassfish application server. Other application servers will also have an own version of this class. In the above web.xml a specific Metro Servlet listener is initiated. Also the webservice will point to a Metro servlet implementation. Than on run-time Metro will generate the webservice and service it.

Deploy to Weblogic 10.3

For deployment to Weblogic 10.3 you need to install one of course, and create a domain.
Creating a domain can be done using the configuration wizard. On windows: All Programs> Oracle Weblogic>Weblogic Server 10gR3>tools>Configuration Wizard
(references: C:\utils\weblogicserver10.3\wlserver_10.3\common\bin\config.exe)

Then you’ll need to install Metro in Weblogic. This is done by copying the following files to the *weblogic-domain-home*/lib (for example C:\utils\weblogicserver10.3\domains\base_domain\lib\):
  • webservices-rt.jar
  • webservices-tools.jar
  • webservices-api.jar
On some Application servers using the Sun 1.6.0 JDK, the webservices-api.jar should be set in the *jdk_home*/lib/endorsed. On my local Weblogic 10.3 server I did not need to.

After this you have to restart your domain.

You can add Weblogic to Eclipse the same way as Glassfish. You’ll have to install the Weblogic pluging though. Choose the ones from the Oracle main entry (not the BEA), because Weblogic 10.3 is from the Oracle BEA era.

You cannot deploy your project by publishing it from Eclipse. Eclipse will complain that Weblogic will not support the sun-jaxws.xml deployment descriptor.

In your HelloWorld project, make sure you have your java source, web.xml and sun-jaxws.xml compiled and in the right folders. Then export your project to a WAR file.

This War file can be deployed to Weblogic using the console (localhost:7001/console). In the console click on Deployments and then install or update. Upload the war to *weblogic-domain-home*\servers\AdminServer\upload\ . If you point directly to your war-file, it is locked by Weblogic.

Weblogic will see that it is a Web-application, but it will not see the Webservice. This is probably because the wsdl and xsd are generated by Metro on deployment time/startup of the Webapplication So you cannot test it from the console. But the wsdl will be on:
http://localhost:7001/HelloWorldWSAnt/HelloWorldWSAnt?wsdl.
I did not try it yet, but it might be possible to register the generated wsdl as a post-deploy step in WebLogic. Maybe that this enables the console to better manage the webservice application.

Usefull Annotations

Earlier I mentioned that it's all in the Annotation really. In the above example I used the bottom-up approach (in the Metro-samples called the "from-java" approach). The HelloWorld example just receives a string and responses with one. But in reqular projects you want to return more sophisticated structures. And then you might want to do the top-down approach, starting with WSDL. The side affect there is that if you change the WSDL you generate the java-implementations, but you have to manually recouple those with your functional code.
I did the from-java approach so I create a compilable set of my functional and webservice code. And then I generate the webservice (XSD and WSDL). This is very usefull if you're in control of the interface. But then you need an enhanced set of annotations to refine your interface.
With this set I managed to manipulate the outcome of my WSDL and XSD generation to match the design. The full description of the annotation you can find at file:///*metro-home*/docs/annotations.html or in the Latest Online Doc: https://jax-ws.dev.java.net/nonav/2.1.7/docs/annotations.html.

Webservice
This is, I think, the basic annotation. This makes the webservice. Actually you need only this one to turn a class into a webservice.
Example: @WebService(name="HelloWorldWS", serviceName="HelloWorldWS")
Other attributes:
  • targetNamespace
  • endpointInterface
  • portName
  • wsdlLocation (Not currently used by Metro 1.5 FCS)
WebMethod
This one just denotes which methods are to be exposed as Webservice Operations.
Example: @WebMethod
Attributes:
  • operationName (defaults to the java name)
  • action (namespace of the wsdl)
  • exclude (to exclude the method from the webservice, defaults to false)

WebParam
To specify the name of the parameter as it appears in the Schema of the request message in the generated XSD. If not used, the parameters are named positional, like 'arg0', 'arg1', ...
Example: @WebParam(name="userName") String userName
Other Attributes:
  • targetNamespace
  • mode
  • header
WebResult
Name of the result variable, the root element in the response message in the XSD.
Example: @WebResult(name="Greeting")

RequestWrapper and ResponseWrapper
These I found are very usefull. With these you can influence the name of the request and response messages, theire namespace and the name of the generated request and response classes.
Example:
@RequestWrapper(localName = "HelloWorldReq", targetNamespace = "http://webservice.darwin-it.nl/", className = "nl.darwin-it.webservice.jaxws.HelloWorld")
@ResponseWrapper(localName = "HelloWorldRsp", targetNamespace = "http://webservice.darwin-it.nl/", className = "nl.darwin-it.webservice.jaxws.HelloWorldResponse")

Mark that for these two the webservices-api.jar has to be added to your project. You might have the GlassFish 2.1 Java EE 5 system library added but this does not have the webservices-api.jar added to it. The corresponding classes for these two annotations are there.
You have to do these imports:
  • import javax.xml.ws.RequestWrapper;
  • import javax.xml.ws.ResponseWrapper;
For the other annotations you have to do the corresponding imports from javax.jws.*.
Overall example:
package com.hello.sample;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@WebService(name="HelloWorldWS", serviceName="HelloWorldWS")
public class HelloWorld {
  @WebMethod
  @WebResult(name="Greeting")
  @RequestWrapper(localName = "HelloWorldReq", targetNamespace = "http://webservice.darwin-it.nl/", className = "nl.darwin-it.webservice.jaxws.HelloWorld")
  @ResponseWrapper(localName = "HelloWorldRsp", targetNamespace = "http://webservice.darwin-it.nl/", className = "nl.darwin-it.webservice.jaxws.HelloWorldResponse")
  public String hello( @WebParam(name="userName") String name){
      return "Hello "+name;
  }
}

Conclusions and More information

With Metro it is really easy to generate an Application Server independend Webservice. With the annotations it is also possible to influence the outcome of the XSD and WSDL generation.
For more information: