Publish REST service with Java SE - java

I am trying to find a simple way to publish my RESTful web service using JAX-RS 2.0 with Java SE using Jersey and/or the Java SE build-in http server.
I want to keep my dependencies to the minimum so i wanted to avoid grizzly and also do not want to use any external application server.
Can you point me how to publish a rest service with this requirements?
Thanks in advance,
I mean to achieve somethig like this:
public static void main(String args[]) {
try {
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer("http://localhost:8080/calculator/",new ResourceConfig(SumEndpoint.class));
System.in.read();
server.stop();
} catch (IOException ex) {
}
}
... but avoiding the grizzly dependency

If you just depend on
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jdk-http</artifactId>
<version>2.2</version>
</dependency>
you can then start the server
JdkHttpServerFactory.createHttpServer(URI.create("http://localhost:8090/root"),
new MyApplication());
where MyApplication extends ResourceConfig to obtain resource scanning.
#ApplicationPath("/")
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("...");
}
#GET
#Produces("text/plain")
public Response foo() {
return Response.ok("Hey, it's working!\n").build();
}
}
There may a better way to control the server life cycle, but that eludes me for the moment.

Related

Force deploy of web application to fail on Tomcat

We are researching the possibility to migrate some web JSF applications from Payara 5 to Tomcat 9 (TomEE 8). We are using Java 11 and Java EE 7/8. Our applications connect to a backend server using RMI. At the moment, with Payara 5, when the code that connects us to the backend server fails (exception is thrown because server is unavailable or credentials defined in web.xml are invalid), the deployment fails.
See this piece of code:
public class MainServlet extends HttpServlet {
//constructor, variables etc.
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
//read configurations from web.xml
try {
connectToBackendServer();
catch (Exception e) {
throw new UnavailableException("Cannot connect to Backend Server");
}
}
//other methods
}
The above piece of code makes the deployment fail on Payara 5, but Tomcat 9 allows the deployment. With Tomcat we notice that the backend is not ok by checking the logs or by trying the front-end and getting the errors. See the below picture where the NullPointerException is thrown by our connectToBackendServer() method.
We are fully aware that this is not the best approach as the backend may fail later, after the successful deployment, but at least we are covering the cases when the configuration from web.xml is wrong.
Can we achieve a similar functionality with Tomcat 9(TomEE 8)?
Thank you all in advance!
..
Move your logic to a ServletContextListener and throw a runtime exception from contextInitialized(). On many servers this will fail the deployment and any requests to the application will return error 500. The spec does not require this exact behaviour though, so the outcome is slightly different between servers.
This is an example implementation using a ServletContextListener that fails the deployment:
package com.example;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;
#WebListener
public class ExampleServletContextListener implements ServletContextListener{
#Override
public void contextInitialized(ServletContextEvent e) {
try {
callThatFailsAndThrowsAnException();
catch (Exception e) {
throw new UnavailableException("Something went very wrong - I'm bailing out.");
}
}
#Override
public void contextDestroyed(ServletContextEvent e) {
/* Application shutdown */
}
}
#WebListener registers the context listener with the container. If you are using an older version of JakartaEE/JavaEE and the annotation is unavailable, you can register the context listener in web.xml instead.

Accessing JAX-WS Published Endpoint is Not Working

I am trying to create a Web service using JAX-WS. I do have a very basic Java project with the following:
EmployeeService .java
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService
public class EmployeeService {
#WebMethod
public String getEmployee(String id) {
return "Vlad Danila";
}
}
Exporter.java
import javax.xml.ws.Endpoint;
import services.EmployeeService;
public class Exporter {
public static void main(String[] args) {
Endpoint.publish("http://localhost:8080/hello",
new EmployeeService());
System.out.println("Successfull!");
}
}
Running the above will throw no error and print "Successfull!".
However, accessing http://localhost:8080/hello on browser gives This page isn’t working.
What am I missing?
I did an example with your code, and it works.. you have to add this to the browser to see
http://localhost:9999/ws/hello?wsdl
This is the url on my case. Then consume it with soap ui or another ws client.
The error you see its cause you are doing a get request on that url and not a soap request.
You don't give much context about what you are doing. JAX-WS is supposed to run in container. Do you run in container which is JEE compatible. See this tutorial, especially the last part:
https://docs.oracle.com/javaee/6/tutorial/doc/bnayn.html#gjyge
If you want something simple, I would recommend to make a spring-boot app, which will work out of the box for you. Forget about heavy JEE containers and try to run a simple spring-boot app which have integrated server inside the spring-boot app.
Here is a link to follow: https://spring.io/guides/gs/rest-service/

Different web service object after each call

I am new with Java EE and SOAP. I have tried to create a simple web service application and its client (environment: NetBeans 7.2.1 IDE, GlassFish Server 3.1, Java 1.6).
Web service code:
package simplews;
import javax.jws.*;
#WebService(serviceName = "SimpleWebService")
public class SimpleWebService {
String something = null;
#WebMethod(operationName = "setSomething")
#Oneway
public void setSomething(#WebParam(name = "smth") String smth) {
something = smth;
}
#WebMethod(operationName = "getSomething")
public String getSomething() {
return something;
}
}
Client application code:
package simpleclientapp;
import simplews.*;
public class SimpleClientApp {
public static void main(String[] args) {
SimpleWebService_Service service = new SimpleWebService_Service();
SimpleWebService port = service.getSimpleWebServicePort();
port.setSomething("trololo");
String smth = port.getSomething();
System.out.println(smth);
}
}
Unfortunately, the client application printed out null. After short investigation I have realised, that on the server side a new SimpleWebService object is created for each client call (sounds like stateless approach).
What is wrong here? Why the client port does not refer to the same WS object for each call?
Web services are stateless by nature. In order to keep state between requests, you have to persist the data (in a file,database etc.).
You're right, JAX-WS web services are stateless by default and you can't rely on something thatviolates this premise. Follow a different approach in storing such values. You can read this doc Java TM API for XML Web Services (JAX-WS) Stateful Web Service with JAX-WS RI, if you really want to follow the direction in your post.

Integrate Jersey with RMI

I have a Java Jersey project, where I am running an application. On the other hand I have a project were there is a RMI application how can I put this two to work together. In other words how can I intergrate RMI/IIOP into a Jersey application.
I was thinking of something like this:
#Path("/items")
public class ItemsResource {
#Context
UriInfo uriInfo;
#Context
Request request;
Stuber s = new Stuber();
#GET
public Response get() throws RemoteException {
}
Were I have an external class in the Jersey Project that will work as a client to connect with the RMI/IIOP
public class Stuber {
Context ic;
iRemoteLogic logic;
public Stuber() {
super();
Object objref;
try {
ic = new InitialContext();
objref = ic.lookup("LogicService");
System.out.println("Client: Obtained a ref. to Hello server.");
logic = (iRemoteLogic) PortableRemoteObject.narrow(
objref, iRemoteLogic.class);
What should I add to the Stuber class to be able to work as an RMI/IIOP client?
Thanks :)
NOTE: I followed this tutorial for the RMI/IIOP
You would need to provide somewhere an implementation of iRemoteService that is exported via RMI/IIOP (i.e. PortableRemoteObject), and register it via JNDI as LogicService. I doubt the latter is going to work: surely you will need to provide a protocol and host to JNDI.

How to mock a web server for unit testing in Java? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
I would like to create a unit test using a mock web server. Is there a web server written in Java which can be easily started and stopped from a JUnit test case?
Wire Mock seems to offer a solid set of stubs and mocks for testing external web services.
#Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
#Test
public void exactUrlOnly() {
stubFor(get(urlEqualTo("/some/thing"))
.willReturn(aResponse()
.withHeader("Content-Type", "text/plain")
.withBody("Hello world!")));
assertThat(testClient.get("/some/thing").statusCode(), is(200));
assertThat(testClient.get("/some/thing/else").statusCode(), is(404));
}
It can integrate with spock as well. Example found here.
Are you trying to use a mock or an embedded web server?
For a mock web server, try using Mockito, or something similar, and just mock the HttpServletRequest and HttpServletResponse objects like:
MyServlet servlet = new MyServlet();
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
HttpServletResponse mockResponse = mock(HttpServletResponse.class);
StringWriter out = new StringWriter();
PrintWriter printOut = new PrintWriter(out);
when(mockResponse.getWriter()).thenReturn(printOut);
servlet.doGet(mockRequest, mockResponse);
verify(mockResponse).setStatus(200);
assertEquals("my content", out.toString());
For an embedded web server, you could use Jetty, which you can use in tests.
You can write a mock with the JDK's com.sun.net.httpserver.HttpServer class as well (no external dependencies required). See this blog post detailing how.
In summary:
HttpServer httpServer = HttpServer.create(new InetSocketAddress(8000), 0); // or use InetSocketAddress(0) for ephemeral port
httpServer.createContext("/api/endpoint", new HttpHandler() {
public void handle(HttpExchange exchange) throws IOException {
byte[] response = "{\"success\": true}".getBytes();
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length);
exchange.getResponseBody().write(response);
exchange.close();
}
});
httpServer.start();
try {
// Do your work...
} finally {
httpServer.stop(0); // or put this in an #After method or the like
}
Try Simple(Maven) its very easy to embed in a unit test. Take the RoundTripTest and examples such as the PostTest written with Simple. Provides an example of how to embed the server into your test case.
Also Simple is much lighter and faster than Jetty, with no dependencies. So you won't have to add several jar files onto your classpath. Nor will you have to be concerned with WEB-INF/web.xml or any other artifacts.
Another good alternative would be MockServer; it provides a fluent interface with which you can define the behaviour of the mocked web server.
You can try Jadler which is a library with a fluent programmatic Java API to stub and mock http resources in your tests. Example:
onRequest()
.havingMethodEqualTo("GET")
.havingPathEqualTo("/accounts/1")
.havingBody(isEmptyOrNullString())
.havingHeaderEqualTo("Accept", "application/json")
.respond()
.withDelay(2, SECONDS)
.withStatus(200)
.withBody("{\\"account\\":{\\"id\\" : 1}}")
.withEncoding(Charset.forName("UTF-8"))
.withContentType("application/json; charset=UTF-8");
If you are using apache HttpClient, This will be a good alternative.
HttpClientMock
HttpClientMock httpClientMock = new httpClientMock()
HttpClientMock("http://example.com:8080");
httpClientMock.onGet("/login?user=john").doReturnJSON("{permission:1}");
Basically, you then make requests on your mock object and then can do some verifies on it httpClientMock.verify().get("http://localhost/login").withParameter("user","john").called()
Try using the Jetty web server.
I recommend Javalin. It's an excellent tool for mocking the real service as it allows for state assertions in your tests (server side assertions).
Wiremock can be used as well. But it leads to hard to maintain behavioral tests (verify that client calls are as expected).
In the interest of completeness there is also wrapping jetty with camel to make it slightly more user friendly.
make your test class extend CamelTestSupport then define a route ex:
#Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
#Override
public void configure() {
from("jetty:http://localhost:" + portToUse).process(
new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
// Get the request information.
requestReceivedByServer = (String) exchange.getIn().getHeader(Exchange.HTTP_PATH);
// For testing empty response
exchange.getOut().setBody("your response");
....
example maven dependencies to get it:
<dependency> <!-- used at runtime, by camel in the tests -->
<groupId>org.apache.camel</groupId>
<artifactId>camel-jetty</artifactId>
<version>2.12.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.12.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<version>2.12.1</version>
<scope>test</scope>
</dependency>

Categories

Resources