Regarding client side code generation from WSDL - java

I am a new bie to the world of webservices , I have to develop the client side code that is the java code,I have been provided a wsdl which I can see by opening that wsdl in the browser , As i have access to wsdl please let me know how can I generate the client side code from that wsdl itself through Axis 2, any help will be appreciated, Thanks in advance

There are many ways to generate client and server stubs.
you can use WSDL2Code Plug-in approach
This plugin takes as input a WSDL and generates client and server stubs for calling or implementing a Web service matching the WSDL.
add the following section to your POM
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>ws1</id>
<goals>
<goal>wsdl2code</goal>
</goals>
<configuration>
<unpackClasses>true</unpackClasses>
<databindingName>adb</databindingName>
<packageName>ma.glasnost.sample.axis2-maven</packageName>
<wsdlFile>src/main/resources/ws.wsdl</wsdlFile>
<outputDirectory>target/generated-sources</outputDirectory>
<syncMode>sync</syncMode>
</configuration>
</execution>
..... if you have many web services
</executions>
</plugin>
Also add axis2 jars as a dependency
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2</artifactId>
<version>1.4</version>
</dependency>

Here a brief overview what you will have to do to generate the client-side java code:
Open the URL pointing to wsdl document in the webbrowser.
Save that webpage as a xml document.
Rename the file to have a .wsdl extension (optional)
Then you need to run the WSDLToJava java file through the java command this class will be contained in the axis.jar
Provide the wsdl filename as an argument to this java file.
Provide all the jar files needed as a classpath argument to this java command
So your command will look something like below:
java -classpath axis.jar;%CATALINA_HOME%/shared/lib/commons-httpclient.jar;%CATALINA_HOME%/shared/lib/log4j.jar;%CATALINA_HOME%/shared/lib/commons-logging.jar;wsdl4j.jar;commons-net.jar;commons-discovery.jar;jaxrpc.jar;soap.jar;saaj.jar org.apache.axis.wsdl.WSDL2Java your_wsdl_fileName.wsdl

If you are using Eclipse then use Java code generation as mentioned in this link.http://axis.apache.org/axis2/java/core/tools/eclipse/wsdl2java-plugin.html#WSDL2Java

Related

Can't import proto file from java file Intellij id

I'm trying to import a proto file from a java file in IntelliJ IDEA.
I have a file called A.proto and a file called B.java. I try to import a class Info from the A.proto file in the B.java file like this:
import A.Info;
However, IntelliJ IDEA doesn't look to support proto files and says my class doesn't exist. I installed both plugins Protobuf Support and Protocol Buffer Editor. But it still doesn't work. Any idea?
Problem
IntelliJ recognizes protocol buffer files, but they are not Java, so the Java Compiler doesn't know what to do with them.
Solution with Maven
You can compile those protocol buffers to Java files, which is the step you are currently missing. The best way I know is to use a Maven plugin to do this.
<plugin>
<groupId>com.github.os72</groupId>
<artifactId>protoc-jar-maven-plugin</artifactId>
<version>3.11.4</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<protocVersion>3.0.0</protocVersion> <!-- 2.4.1, 2.5.0, 2.6.1, 3.0.0 -->
<includeDirectories>
<include>src/main/resources/protobuf</include>
</includeDirectories>
<inputDirectories>
<include>src/main/resources/protobuf/</include>
</inputDirectories>
</configuration>
</execution>
</executions>
</plugin>
And dependency for the Protocol Buffer classes:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.4</version>
</dependency>
With this plugin, Intellij will find the created Java classes, after having initially created the sources. This way, only your Protocol Buffer files need to be in Source Control. You let the plugin take care of the compilation to Java.
After creation of the Java classes, you can use them in the rest of your code. You can even view the generated Java classes in the target/generated-sources folder in your Maven Project.
Here's what the mapping between Protocol Buffers and Java looks like:
DistanceWalked.proto
package example;
message DistanceWalked {
string userId = 1;
double distance = 2;
}
DistanceWalkedOuterClass.DistanceWalked.java (generated)
package example;
public class DistanceWalked {
//properties This class isn't pretty...
}
(Full code example with protocol buffers and Maven plugin can be found here: https://github.com/TomCools/protocol-buffers-example)
Link to plugin source: https://github.com/os72/protoc-jar-maven-plugin
Solution without Maven
Without Maven, you have to download the command-line compiler. Documentation on that can be found here: https://developers.google.com/protocol-buffers/docs/javatutorial#compiling-your-protocol-buffers
The proto file is just the description of the message format. It does not contain code that can be interpreted directly in a java context.
The idea of the proto file is to provide a generic, language agnostic specification of the message format.
Based on the proto file, you can generate the corresponding java code. This code can then be used and imported in your java project.
Have a look here on how to generate code from a proto file: https://developers.google.com/protocol-buffers/docs/javatutorial#compiling-your-protocol-buffers
Incase anyone is still stuck -
I found that specifying the path to Intellij fixes the problem:
Preferences -> Languages and Frameworks -> Protocol Buffer -> Uncheck "Configure automatically"
And then add the path to the file.
It should be good for xolstice or os72!

Using jaxws-maven-plugin with -clientjar option

I'm using jaxws-maven-plugin to execute wsimport for a web service consumer app. I'm using the -clientjar option on wsimport which was introduced with JAX-WS 2.2.2 RI in 2010. I do this because I want to bundle the WSDL within the jar.
I don't have a problem crafting the pom. For plugin configuration I do something like:
<configuration>
...
<args>
<arg>-clientjar</arg>
<arg>bundled-wsdl.jar</arg>
</args>
</configuration>
When I execute a build my created jar, lets call it myapp.jar, has file bundled-wsdl.jar within it. Inside the bundled-wsdl.jar's META-INF directory I find the wsdl and xsd just as I like them. I'm also quite happy with the generated java code that come as a result of using the -clientjar option. So far so good.
But this stuff should be in myapp.jar's META-INF, right?
The fact that it sits within bundled-wsdl.jar's META-INF doesn't help me a lot.
The funny thing is that I do in fact get a wsdl file in myapp.jar's META-INF which makes the application actually work. How it gets there I don't know. Also the xsd file isn't there, only in bundled-wsdl.jar's META-INF.
The basic question is how to correctly use wsimport -clientjar option in a Maven project ?
Java 1.7.0_45.
The -clientjar option is really poorly documented, IMHO.
Here's how I believe it works:
When the -clientjar <jarfile> option is used three things are happening:
You'll get a <jarfile> generated in the directory pointed to by
the -d argument to the wsimport tool. This will contain within
it both WSDL and any relevant XSD files as well. This little bundle will not be used for anything at all. If you want to make use of it it would be entirely up to you. But before you do see (2) below. I'm not sure what to use this jarfile for other than as a form of documentation.
You'll get a copy of the WSDL put into a file called
META-INF/wsdl/<svcname>.wsdl. The generated classes will use this
file in the no-arg proxy constructor. So this is what will actually
be used if you request a bundled WSDL file with the -clientjar
option.
The generated code will change so that wsdlLocation, if you are using the default no-arg constructor on the #WebServiceClient class, will be that of the bundled WSDL (from (2)), rather than the remote WSDL. Indeed if you use -wsdllocation on your command line together with -clientjar then whatever you specify with -wsdllocation will have no effect as -clientjar will take precedence.
So we must focus on (2) and (3) because that's the only one being actually used ... at least if you use the generated code as-is.
It is interesting to note that the result of (2) is only a WSDL file. This file may have embedded links to XSD files but as far as I can tell such link will never be followed. The reason is that when we say a web service consumer needs the WSDL at runtime it really only needs the WSDL itself, at not the schema. The schema is "hardcoded" into the consumer and there's no way of changing it at runtime. Hence there's no reason to read schema information at runtime. (THIS IS FROM MY UNDERSTANDING)
Second thing to note about the WSDL that's included with (2): It is really just a copy of the original WSDL so it may not have endpoint you want. Actually in most cases it won't. This means that in this situation you'll need to set the endpoint yourself :
// Use no-arg constructor. Means it uses the WSDL bundled into the
// META-INF/wsdl directory rather than trying to retrieve WSDL over the
// network.
service = new HelloSvc_Service();
hello = service.getHelloSvcPort();
// Since we're using a bundled WSDL the web service URL cannot
// be derived from that (it would be wrong!). So we have to set
// it explicitly.
((BindingProvider) hello).getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://myhellowebservice-address");
The documentation for this plugin is a joke. A workaround is to manually extract the contents from the client jar after it is created like follows:
<build>
<plugins>
<plugin>
<!--
Generates JAXWS classes for all of the WSDL files in $[project.base.dir}/src/wsdl.
-->
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<args>
<arg>-clientjar</arg>
<arg>${project.build.directory}/wsimport-client.jar</arg>
</args>
<wsdlUrls>
<wsdlUrl>https://webservice.com/service.wsdl</wsdlUrl>
</wsdlUrls>
</configuration>
</execution>
</executions>
<configuration>
<target>2.1</target>
<verbose>true</verbose>
</configuration>
</plugin>
<plugin>
<!--
Unjar the wsimport-client.jar created in the jaxws-maven-plugin to the WAR's classes folder
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<target>
<unzip src="${project.build.directory}/wsimport-client.jar" dest="${project.build.directory}/classes" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
taken from here: https://gist.github.com/mpellegrini/5439304
I had the same issue, and I had to unzip the created jars and re-zip in one single jar (so, putting the wsdl file from the inner jar in the final jar).
Thanks to peterh comment, I think I understood the "trick": in Maven output I can see a log like
jaxws:wsimport args: [..., -Xnocompile, -clientjar wsdl.jar, ...]
so the wsimport command is launched without compiling che code, and in fact a wsdl.jar is created in the target/classes folder.
I think wsimport is just generating the sources and the jar with the wsdl, then the compilation and the packaging is done in the following steps.

maven generate web service in java

I'm new to maven, and I want to use maven to generate the java code from a wsdl file (using the wsimport plugin ?), which is in my project (not in a url).
I think the wsdl file should be somewhere in myprojet/src/main/resources, and the generated sources in myproject/target/generatedsources/ws.
If the choice of these places ok ? If so, how can I create the sources from the wsdl to the designated folder using maven ? Can I choose the java package name of the sources ? Should I ? Should I then make a jar file out of the sources ? How can I make sure that the generated sources are accessible for the compilation (in the classpath) ?
thank you.
There are several ways to do this with the wsimport plugin, but most examples would require more knowledge of your pom.xml
Apache CXF is a popular free plugin for this exact purpose
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/myService.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
NOTE: You can definitely make a jar out of the generated sources, but this would be a separate entry inside your POM
check out Apache's Axis2 -- it's designed specifically to help generate code based on an WSDL for web services. Basically it's exactly what you are looking for:
http://axis.apache.org/axis2/java/core/
EDIT: To expand, I typically will run the wsdl2java(.bat or .sh) file and point it to the wsdl (either on the web or local copy) and it generates everything else. It can even package it all into a jar for you (my preferred method because it's "cleaner"). You likely won't have any need to go into the generated code and change anything, you just end up adding that jar to your classpath then import like any other library and use it.

Maven Configuration for Converting a WSDL 1.1 to WSDL 2.0 Using woden-converter-maven-plugin

I'm looking to convert a WSDL version 1.1 into a WSDL 2.0 format as part of our maven build process.
I've come across the Woden Converter utility which uses XSL to do this conversion, and would like to use it. However, there seems to be no documentation or examples (that I can find) on how to configure or use the related maven plugin: woden-converter-maven-plugin
Does anyone have experience with this, and could they please share the maven plugin config details?
Justification (for those that require it):
We have a contract-first Web Service and have a recent requirement to expose our WSDL in 2.0 format to one particular client. To save on maintaining two identical WSDLs, we'd like to maintain the 1.1 wsdl and have the build process auto-generate the 2.0 version.
Here are the sources for the plugin. There's not much you can set. Check the fields. You can set those up in the <configuration/> section of your plugin.
Consider this:
<plugin>
<groupId>org.apache.woden</groupId>
<artifactId>woden-converter-maven-plugin</artifactId>
<version>1.0M9</version>
<executions>
<execution>
<id>convert</id>
<goals>
<goal>convert</goal>
</goals>
<configuration>
<wsdl><!-- File or URL of wsdl1.1 document.Also multiple
WSDL files can be specified as a comma separated
list. -->
</wsdl>
<targetNS>
<!-- New target namespace for WSDL2.0 document. -->
</targetNS>
<targetDir>
<!-- Target directory for output, default
location is project build directory. -->
</targetDir>
<sourceDir><!-- Source directory for output. --></sourceDir>
<verbose><!-- Verbose mode --></verbose>
<overwrite><!-- Overwrite existing files. --></overwrite>
</configuration>
</execution>
</executions>
</plugin>

Creating a web-service client directly from the source

I am trying to generate the WS client jar directly from the #Webservice class(es).
Let's take this example :
package com.example.maven.jaxws.helloservice;
import javax.jws.WebService;
#WebService
public class Hello {
public String sayHello(String param) {
return "Hello " + param;
}
}
I can generate a war file and use GlassFish to serve this web service, and from there I can use the glassfish WSDL URL to generate the client sources.
What I am trying to do is to skip the GlassFish part.
From my maven project defining the webservice, I would like to use the jaxws-maven-plugin to create the client classes but I cannot find any way to specify the actual URL of the webservice.
It should be possible, right?
#see also Creating a web-service client with a known but inaccessible wsdl
Creating a web service client application always starts with an existing WSDL file (unlike developing a web service provider) and, even if this is not the only way, I'd suggest to use the wsimport tool (see 5 Techniques for Creating Java Web Services from WSDL for other options but I won't cover them).
So, in your client project, add the following snippet to your pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlUrls>
<wsdlUrl>
http://localhost:8080/helloservice/HelloService?wsdl
</wsdlUrl>
</wsdlUrls>
<packageName>com.example.maven.jaxws.helloclient</packageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<bulid>
The jaxws-maven-plugin:wsimport mojo is bound by default to the generate-sources life cycle phase so running any phase posterior to generate-sources will trigger the jaxws:wsimport goal.
Note that this is really a minimal configuration. If you want more details/control, check the documentation of the wsimport mojo.
For example, to use files instead of URLs for the WSDL (and to generate Java code in a location more compliant with maven best practices), use:
<configuration>
<sourceDestDir>${project.build.directory}/generated-sources/wsimport</sourceDestDir>
<wsdlDirectory>${basedir}/src/wsdl</wsdlDirectory>
<wsdlFiles>
<wsdlFile>foo.wsdl</wsdlFile>
<wsdlFile>bar.wsdl</wsdlFile>
</wsdlFiles>
...
</configuration>
Update: To invoke a pre-configured stub (using the endpoint address from the WSDL), the code is:
Hello port = new HelloService().getHelloPort();
String result = port.sayHello("Duke!");
In order to invoke an endpoint whose address is different from the one specified in the WSDL, define the new endpoint URL and the QName:
URL endpoint_new = new URL( "NEW_ADDRESS_HERE" );
QName qname = new QName( "http://"+"ORIGINAL_PACKAGE", "SERVICENAME" );
Hello port = new HelloService( endpoint_new, qname ).getHelloPort();
where ORIGINAL_PACKAGE is the package where the service published in, SERVICENAME is the name of the service we need, for example, HelloService.
You should use <wsdlLocation> option to give the location of the service where the WSDL file is going to be available after deployment.
Using -wsdlLocation switch
There is another easy way to do it -
just run wsimport with -wsdlLocation
switch and provide the WSDL location
value which is relative to the
generated Service class and you need
to put this WSDL file at this relative
location.
See the post for more details.

Categories