Publishing multiple Endpoints with built-in Java JAX-WS web server - java

So I have 2 implementations, Impl1 and Impl2, of a web service interface class. I would like to publish both under the same domain and port but with different URLS:
http://some.domain.asd/ws1 and http://some.domain.asd/ws2
Apparently, I should be able to create a configuration where I have 2 Endpoints, one for each implementation, bound to a single web server instance.
Note that I am not deploying but using the Java 7 internal publishing mechanism.
I noticed that instead of calling
Endpoint.publish(URL, new Implementor());
to directly publish a web service, I can call
Endpoint ep = Endpoint.create(new Implementor());
ep.publish(serverContext);
to publish the Implementor at a specific serverContext. What exactly is such a serverContext and how do I use it? I noticed that the publish method instantiates a javax.xml.ws.spi.Provider class and uses it for publishing purposes. But that is apparently not what I am looking for. Ideally, I would like a solution that resembles something like this:
Object serverContext = new Server(URL);
Endpoint impl1 = Endpoint.create(new Impl1());
Endpoint impl2 = Endpoint.create(new Impl2());
impl1.publish(serverContext);
impl2.publish(serverContext);
Can this even be done with the built-in publishing system, maybe using EndpointReferences objects? Or am I required to use a web service container to deploy my Endpoints seperately?

Publishing multiple Endpoints running on the same port could be achieved with this code :
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Endpoint.publish("http://localhost:8888/ws/send", new SendServiceImpl());
Endpoint.publish("http://localhost:8888/ws/send23", new SendServiceImpl());
}
}
Running this locally in Eclipse it works , but when you deploy it to another server its broken.
To fix this you can either use http://0.0.0.0:8888 instead of localhost or the correct internal ip-address of the server.
You find it running:
windows: ipconfig
unix: ifconfig
It looks something like this: 192.168.100.55.

I stumbled across this problem today; I kept getting "java.net.BindException: Address already in use" when publishing two different endpoints to the same host+port. The solution is to instantiate the HttpServer yourself and "bind" each endpoint to this server:
package mypackage;
import com.sun.net.httpserver.HttpServer;
import javax.xml.ws.Endpoint;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public static void main(String[] args) throws IOException {
final HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 8080), 16);
final Endpoint fooEndpoint = Endpoint.create(new FooImpl());
fooEndpoint.publish(httpServer.createContext("/Foo"));
final Endpoint barEndpoint = Endpoint.create(new BarImpl());
barEndpoint.publish(httpServer.createContext("/Bar"));
httpServer.start();
}

Related

Generating java files from WSDL - test vs prod WSDL

I am developing integration with local delivery service and they gave me URL to WSDL files.
One points to test environment and other to the production environment.
test: http://tsteportal.posta.si/Services/eSpremnica.Wcf/eOddaja.svc
production: https://eportal.posta.si/Services/eSpremnica.Wcf/eOddaja.svc
I would like to know if I really need to generate java files from both, or simply put, when deploying application to production, do I really need to generate files from production WSDL?
Isn't there any way to just change endpoint from test to production?
I've also noticed that generated files from Eclipse and wsimport are not the same, for example using Eclipse, it doesn't generate ObjectFactory class.
You can use the same artifacts generated for both services if the only difference is the endpoint.
Example:
import java.net.URL;
public class Main {
public static void main(String[] args) throws Exception{
URL qaWsdl = new URL("http://tsteportal.posta.si/Services/eSpremnica.Wcf/eOddaja.svc");
URL prodWsdl = new URL("https://eportal.posta.si/Services/eSpremnica.Wcf/eOddaja.svc");
boolean isQA = Boolean.valueOf(args[0]);
//Pass whichever WSDL endpoint you need
EchoService service = new EchoService((isQA) ? qaWsdl : prodWsdl);
Echo port = service.getEchoPort();
}
}

Vertx Eventbus not working in Java

OS Linux
JDK 1.7.0_67
Vert.x 2.1.5
Just getting started for wiring some of the vertx examples found on github.
Due to the manual want to try out a simple Sender <-> Receiver example, over EventBus. Many hours later, no ping, neither a hello world.
Anyone has an idea, what I'm missing on this simple code:
Sender.java
import org.vertx.java.platform.Verticle;
public class Sender extends Verticle {
public void start(){
vertx.eventBus().send("ping-address", "Hello");
}
}
Receiver.java
import org.vertx.java.core.Handler;
import org.vertx.java.core.eventbus.EventBus;
import org.vertx.java.core.eventbus.Message;
import org.vertx.java.platform.Verticle;
public class Receiver extends Verticle {
public void start() {
EventBus eb = vertx.eventBus();
eb.registerHandler("ping-address", new Handler<Message<String>>(){
#Override
public void handle(Message<String> message) {
container.logger().info("Message: "+message.body());
}
});
container.logger().info("PingVerticle started");
}
}
Running both in seperate JVM instances on the same machine, with following CLI command:
vertx run Receiver.java
> Succeeded in deploying verticle
another console:
vertx run Sender.java
> Succeeded in deploying verticle
The way you're running the vertices, they won't be able to see each other. They're essentially being started as completely separate processes with clustering disabled (the default). You have to run the vertices in cluster mode in order to get them to locate and communicate with one another. Use the -cluster option to enable Hazelcast clustering. You may also want to specify -host or -port.
If you continue seeing problems with even bus communication after that, enable Hazelcast logging and ensure the two nodes see each other. You may have to alter cluster.xml (the Hazelcast configuration) if your network does not support multicast.
Might be helpful for those who is using programmatic way of clustering.
Please check you have the following values set in your vertx options:
VertxOptions options = new VertxOptions().setClustered(true)
.setClusterHost("198.12.12.12")
.setHAEnabled(true)
.setHAGroup("dev");
Vertx.clusteredVertx(options, res -> System.out.println(res.succeeded()));

Access an service in jboss through JNDI (RMI?)

I need to make an service in jboss and access it through JNDI on the client side.
I have been playing around a bit with JNDI and made something like this on the client side:
import javax.naming.*;
public class App {
public static void main(String[] args) throws NamingException {
App app = new App();
app.setSysProp();
app.setObject();
app.getObject();
}
public void setSysProp() {
System.setProperty(Context.PROVIDER_URL, "127.0.0.1:1099");
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
}
public void setObject() throws NamingException {
Context context = new InitialContext();
MyObject obj = new MyObject();
obj.setName("NameOfMyObject");
context.bind("obj", obj);
}
public void getObject() throws NamingException {
Context context = new InitialContext();
MyObject obj = (MyObject) context.lookup("obj");
System.out.println(obj.getName());
}
}
This only binds and object to jndi on the client side and later retrieves it.
Now what i want is to bind a similar object on the server side (Jboss 4.2.3) and through it make some operations on the server. How can this be done? Ive read that something named RMI should be used in this case but what exactly is that and how to use it?
Ive read that something named RMI should be used in this case but what exactly is that and how to use it?
RMI is the Java standar API for Remote Method Invocation. It allows you execute a method on a object that reside in other Java Virtual Machine. Take in mind that you don't need a application server like JBoss to communicate with a remote java object. This link provides a simple tutorial.(notice that JBoss or any other app server is not mentioned)
I need to make an service in jboss and access it through JNDI on the client side.
This is a different thing. Although, JBoss (as a Java EE specification compliant server) use RMI extensively, you don't need understand how this API works. What you need is to create a server side component called EJB which allows you to have a service running on a server.
How can this be done?
There are hundred of tutorials about how to implement a basic EJB. Choose one compatible with your JBoss version due to some implementation details often change from one version to another.
You will also find that EJB specification has been evolving. With JBoss 4.2.3 and Java 5 you can start with EJB 3.0 which is easier than the previous one (2.1)

Java web service client + Axis + Eclipse + Tomcat

I'm new to java web services.
Now i'm trying to create a web service client to access a WSDL based web service. So using eclipse i generated the required client stubs/Binding stubs/Port/Port proxy/ServiceLocator etc.
According to my understanding next step is to create a class with the main method to invoke it. Can anyone help me to write that piece of code or at least some links to refer?
EDITED
Thank you so much for the hint #pavan-kumar. Finally i come up with following code and it works. Thanks again.
package clients;
import requiredClasses;
public class TestClient {
public static void main(String args[]) throws Exception
{
TestPortProxy tProxy = new TestPortProxy();
RequestEntity rEntity = new RequestEntity();
rEntity.setAttribute1(100);
rEntity.setAttribute2("value1");
tProxy.webServiceAction(rEntity);
}
}
You already generated required client files with the WSDL ,so next create your own class in that create an object for proxy class which is generated by WSDL, by using that object you can call web service methods in your application.

Embedded Jetty: Different ports for internally- and externally-visible endpoints?

I've got a REST app that uses embedded Jetty as the server. Most of the endpoints need to be publicly-visible (and have appropriate authentication built in), but a few are for internal-use only. I'd like to avoid the overhead of authentication on those and instead use the firewall to restrict access:
Externally-visible endpoints are served on port 10000, which the external firewall leaves open.
Internally-visible endpoints are served on port 20000, which the external firewall blocks.
However, I can't figure out how to achieve this with embedded Jetty. I've tried instantiating two Server objects, one on port 10000 with the appropriate servlet handlers registered and one on port 20000 with the appropriate servlet handlers registered. However, only the server instance that is started second works; requests to endpoints hosted by the one started first result in 404 responses.
The Jetty documentation talks about how to do this with *.xml configurations , but not for an embedded instance.
Any thoughts or ideas? Or is there a better way to achieve the internal/external endpoint isolation I'm after? The hard requirement is that both internal and external endpoints need to "run" in the same JVM.
Edit
Turns out that the problem was related to using Guice and the Guice-servlets extension (issues 618 and 635). Running two embedded Jetty instances works fine as described in James Kingsbery's answer below.
Guice uses a filter (GuiceFilter) registered with server context to get ahold of requests that need request-scoped dependency injection (DI) and to construct servlets and filters that require DI. Unfortunately, it uses a static object to manage the list of servlets and filters associated with it.
In a typical setup, the guice-servlet.jar containing GuiceFilter is included per-application and thus loaded by a different classloader for each application--- and everything works fine. No so with embedded Jetty, where essentially everything is loaded by the default system classloader.
Solution to Guice Problem
The latest master (commit fbbb52dcc92e) of Guice contains an updated GuiceFilter with support for a dynamic reference to the FilterPipeline object (the static object causing the problems). Unfortunately, the constructor to inject the FilterPipeline instance is package-private. So, to use it you need to create a wrapper class in the com.google.inject.servlet package that exposes that constructor:
package com.google.inject.servlet;
import com.google.inject.Inject;
public class NonStaticGuiceFilter extends GuiceFilter {
/**
* Do not use. Must inject a {#link FilterPipeline} via the constructor.
*/
#SuppressWarnings("unused")
private NonStaticGuiceFilter() {
throw new IllegalStateException();
}
#Inject
public NonStaticGuiceFilter(FilterPipeline filterPipeline) {
super(filterPipeline);
}
}
To use this class, create an instance using the injector with your ServletModule installed and register it with your Jetty Context:
// Create the context handler
ServletContextHandler handler = new ServletContextHandler(myServer, "/context");
// Create the injector, registering your ServletModule
final Injector injector = Guice.createInjector(new MyServletModule());
// Add the Guice listener for this injector
handler.addEventListener(new GuiceServletContextListener() {
#Override
protected Injector getInjector() {
return injector;
}
});
// Filter all requests through Guice via NonStaticGuiceFilter.
// Guice will construct the FilterPipeline instance needed by
// NonStaticGuiceFilter.
handler.addFilter(
new FilterHolder(injector
.getInstance(NonStaticGuiceFilter.class)), "/*", null);
My usual crutch in getting started with an embedded Jetty project is the Wicket maven archetype. Here is a class based on that archetype that should do pretty much what you need:
package net.kingsbery;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.bio.SocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;
public class Start {
public static void main(String[] args) throws Exception {
Server server = new Server();
SocketConnector connector = new SocketConnector();
// Set some timeout options to make debugging easier.
connector.setMaxIdleTime(1000 * 60 * 60);
connector.setSoLingerTime(-1);
connector.setPort(10080);
server.setConnectors(new Connector[] { connector });
WebAppContext bb = new WebAppContext();
bb.setServer(server);
bb.setContextPath("/");
bb.setWar("src/main/secret-webapp");
server.addHandler(bb);
Server server2 = new Server();
SocketConnector connector2 = new SocketConnector();
// Set some timeout options to make debugging easier.
connector2.setMaxIdleTime(1000 * 60 * 60);
connector2.setSoLingerTime(-1);
connector2.setPort(20000);
server2.setConnectors(new Connector[] { connector });
WebAppContext bb2 = new WebAppContext();
bb2.setServer(server);
bb2.setContextPath("/");
bb2.setWar("src/main/webapp");
server.addHandler(bb);
server2.addHandler(bb2);
try {
server.start();
server2.start();
} catch (Exception e) {
e.printStackTrace();
System.exit(100);
}
}
}
If you use some other handler, replace that with the webapp handler.
That being said, I'm not sure that this is the right way of doing it.

Categories

Resources