JAX-WS service deployment - java

I am new to web service programming and trying to create a JAX-WS web-service. I have created the following JAX-WS web service in Eclipse:
Creating the service interface:
package test;
#WebService
#SOAPBinding(style = Style.RPC)
public interface AdditionService {
#WebMethod
int add(int a,int b);
}
After that one implementation class:
package test;
#WebService(endpointInterface = "test.AdditionService")
public class AdditionServiceImpl implements AdditionService{
#Override
public int add(int a, int b) {
return a+b;
}
}
Last step:
By using the following code I am publishing the service:
package test;
public class AddtionServicePublisher {
public static void main(String[] args) {
Endpoint.publish
("http://localhost:9999/ws/additionService",
new AdditionServiceImpl());
}
}
I can view the wsdl using the bellow local URL:
http://localhost:9999/ws/additionService?wsdl
But as I don't have any server installed. How, it is getting published? Is server is inbuilt with eclipse?

The Oracle Java documentation states the following
Creates and publishes an endpoint for the specified implementor object at the given address.
The necessary server infrastructure will be created and configured by the JAX-WS implementation using some default configuration.
As JAX-WS is part of the Java SE package, this means the underlying server is depending on what kind of JVM you are running your program at. E.g. on my laptop I am running a Java 8 OpenJDK, in which an instance of "com.sun.net.httpserver.HttpServer" is created.
The fastest way to find out what server ist started in your environment, just jump into the (decompiled) code of the Endoint.java and the implementation(s).
If you want to create a standalone, selfrunning Webservice-jar you might be interested to take a look at Spring-WS (with Spring Boot) or Dropwizard.

Related

WebServices subsystem disabled in Wildfly 23/24 (Jakarta JWS)

I am trying to deploy an extremely simple SOAP Web Service, using Jakarta JWS 3.0.0 on OpenJDK 15, to a clean Wildfy 23/24 instance. The code is as follows:
Interface:
import jakarta.jws.WebMethod;
import jakarta.jws.WebService;
import jakarta.jws.soap.SOAPBinding;
import jakarta.jws.soap.SOAPBinding.Style;
#WebService
#SOAPBinding(style = Style.RPC)
public interface HelloWorldServerInt {
#WebMethod
String sayHelloWorld(String name);
}
Implementation:
import jakarta.jws.WebService;
#WebService(endpointInterface = "ws.HelloWorldServerInt")
public class HelloWorldServerImpl implements HelloWorldServerInt {
#Override
public String sayHelloWorld(String name) {
return "Hello World ! My name is " + name + ".";
}
}
Once I deploy the WAR, I can see it under "Deployments" in the admin console. But if you click "Views / Management Model", under "subsystem", the "webservices" subsystem is disabled, so I cannot see the deployed service, and of course it doesn't work.
I've worked with Web Services before using web.xml file and com.sun.xml.ws.transport.http.servlet.WSServlet servlet, but as far as I know, this is not the way to go, and annotations should be automatically discovered by Wildfly. Am I wrong?
Kind regards.
As #ehsavoie explained in the comments, the problem was using Wildfly 24 instead of Wildfly Preview 24.
Once everything was set up with WF Preview, Web services subsystem was enabled and usable as expected.

Dynamic OSGi service replacement as development aid

We are using Apache Felix annotations to handle all the OSGi stuff in our application. I have a provider class that talks to a server. I have a consumer class that does stuff with data from the server. What I want is to create another provider instance (new class implementing interface) that is for debug purposes only that returns canned responses to requests by the consumer. Ideally I would like the consumer to be unaware of this handoff. It's provider service reference would simply be replaced.
The use case: When the developer is running on a machine without access to the actual server, he presses a button in our running app to switch from the real provider instance to our debug provider instance.
What is the recommended way to accomplish this?
Example code:
public interface IProvider{
public String getDataFromServer();
}
#Component
#Service(value=IProvider.class)
public class RealProvider implements IProvider{
#Override
public String getDataFromServer(){
...
}
}
#Component
#Service(value=IProvider.class)
public class DebugProvider implements IProvider{
#Override
public String getDataFromServer(){
return "Hello World";
}
}
#Component
public class Consumer{
private #Reference IProvider provider;
public void doSomething(){
provider.getDataFromServer();
}
}
If the two providers are in separate bundles, you can stop Bundle A and start Bundle B to switch between implementations of the service.
If the two providers are in the same bundle, you'd need to either drop down to the OSGI API and register/unregister the services manually, or create a proxy version of IProvider that has a debugMode flag and delegates to the specific implementation.

Porting a JavaService app (Windows Service) to run on Websphere - best parent class?

I've been asked to port an existing Java app that runs as a windows service to run on Websphere. It is implemented using JavaService.exe and a stop_method
The type signature of the parent service class is:
public abstract class ParentService {
public static void main(String args[]);
public void requestStop();
}
Note that the main method in the example above is the equivalent of the init method in a servlet (although it is static) - it is used for the same purpose.
What is the equivalent parent class for a continuously running object in the J2EE standard (or even in the Websphere custom standards?)
Assuming the big idea is mapping an init and a shutdown method to a Java interfaces in the Enterprise standards...
It turns out there are four alternatives (and three vendor specific ones):
EJB 3.1 #Startup
Startup Servlet
ServletContextListener
Resource Adapter to Perform as a Startup Class

How do I provide my own web service implementation instance?

I have a web service (JAX-RPC) that runs on application server (Websphere Application Server 7.0).
Normally the development process looks like this:
I write a class with web service implementation (e.g. MyService.java)
The IDE generates web service endpoint interface (e.g. MyService_SEI.java)
The IDE generates configuration XMLs
When the web service is deployed, MyService_SEI is the declared service interface and the application server instantiates a MyService instance by means of the public no-arg constructor.
But what if I want to do constructor injection (i.e. have MyService class without a no-arg constructor) or if I want to provide a dynamic proxy object which implements MyService_SEI and use that?
Is there a way I can take control of the instantiation procedure (like a filter or interceptor) to achieve this?
You can't do constructor injection as Injection always occur after the default constructor is called. If you try to use an injected reference inside the default constructor it will ALWAYS fail, there's no workaround for this as this is mandate by the specification.
So the first option you mentioned is discarded.
For the second option, using a filter or interceptor, you actually have an option. WebSphere WebServices are build using Axis2 implementation and Axis provide a way of implementing Handlers.
You can add handlers into the JAX-WS runtime environment to perform additional processing of request and response messages.
Here's a handler example, from Axis documentation:
package org.apache.samples.handlersample;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SampleProtocolHandler implements
javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
public void close(MessageContext messagecontext) {
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext messagecontext) {
return true;
}
public boolean handleMessage(SOAPMessageContext messagecontext) {
Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
// Include your steps for the outbound flow.
}
return true;
}
}
And than you add a handler.xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chain name="MyHandlerChain">
<jws:protocol-bindings>##SOAP11_HTTP ##ANOTHER_BINDING</jws:protocol-bindings>
<jws:port-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:MySampl*</jws:port-name-pattern>
<jws:service-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:*</jws:service-name-pattern>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
</jws:handler-chain>
an easy method would be to make two classes. one your class with all the bells and whistles (constructor injection etc lets call it worker). and the actual service. the service would delegate what it needs to the worker class, who it can get by calling some factory method.
The factory can even look at some common db or other config to decide which run time instance (which class, what config, shared or common) so you have good separation and power
Just cause you are using one framework/ method of injection does not mean you cannot mix to make it more powerful

Web service client getting NullPointerException from getMyWSPort

I have created a simple web service called TimeServerBean. It's working properly, the GlassFish server is running and I can access the WSDL file from browser. Note this is done on local host.
Next I created a new project and made a web service client and provided the URL to the WSDL file. Then I got some classes generated (JAX-WS).
On my client class I have this code:
public class SimpleClient {
#WebServiceRef(wsdlLocation = "wsdl url here")
static TimeServerBean_Service service;
private TimeServerBean bean;
public SimpleClient() {
bean = service.getTimeServerBeanPort();
}
//methods here
}
Although I get null when I call the getTimeServerBeanPort. During that time the server is up and running. Is there some obvious mistake? TimeServerBean and TimeServerBean_Service are generated classes from the WSDL.
Two suggestions:
DEFINITELY put your method in a try/catch block
Assuming that service itself is null, then try doing an explicit service.create() instead of using the #WebServiceRef annotation. Here's a good example (Websphere, but same principle):
http://www-01.ibm.com/support/docview.wss?uid=swg21264135
The #WebServiceRef annotation is only supported in certain class types. Examples are JAX-WS endpoint implementation classes, JAX-WS handler classes, Enterprise JavaBeans classes, and servlet classes. This annotation is supported in the same class types as the #Resource annotation. See the Java Platform, Enterprise Edition (Java EE) 5 specification for a complete list of supported class types.
I generally do it by creating an instance using the interface and the class.
public class SimpleClient {
// interface TimeServerBean_Service class TimeServerBean
#WebServiceRef(wsdlLocation = "wsdl url here")
static TimeServerBean_Service port = new TimeServerBean.getTimeServerBeanPort();
public static void main(String[] args) {
try {
System.out.println(port);
System.out.println(port.methodWS("args"));
} catch (Exception e) {
e.printStackTrace();
}
}
//methods here
}

Categories