This is my first time dealing with web-services. Simply, I need to send a post request from jersey web service client (inside a webpage implemented in javascript) to a jersey service which is in one of my maven modules.
As I said I've created jersey-server within one of my maven modules and I would like to run it somehow (I do not know how to run a web service program.) before starting client side of my implementation. Through searching on the web, I saw lots of examples but all of them was using tomcat. So my first question is that do I need to use tomcat (or something like this ) in order to run a web service ? Secondly, below I shared my jersey-server module. How could I start to run it ?
package com.exampleProject.rest;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
#Path("/test")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class SiderRecommender {
#POST
#Path("/functiontest")
public List<Recommendation> sampleFunction() {
// return something here. I removed it for simplicity.
}
}
You don't have to run a Jersey app in an installed web server. You can run it in an embedded server, meaning a server that runs in standalone mode with a normal main method.
If you are using Maven, and you are familiar with creating Maven archetypes, you can use the jersey-quickstart-grizzly2 archetype
From Command line
From Eclipse (except use jersey-quickstart-grizzly2)
From Netbeans (See bottom of answer. Also use jersey-quickstart-grizzly2).
This is everything you get for free with the archetype project.
Main.java
package com.underdog.jersey.grizzly;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.io.IOException;
import java.net.URI;
/**
* Main class.
*
*/
public class Main {
// Base URI the Grizzly HTTP server will listen on
public static final String BASE_URI = "http://localhost:8080/myapp/";
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
* #return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in com.underdog.jersey.grizzly package
final ResourceConfig rc = new ResourceConfig().packages("com.underdog.jersey.grizzly");
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
System.in.read();
server.stop();
}
}
MyResource.java
package com.underdog.jersey.grizzly;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* Root resource (exposed at "myresource" path)
*/
#Path("myresource")
public class MyResource {
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* #return String that will be returned as a text/plain response.
*/
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
}
MyResourceTest.java
package com.underdog.jersey.grizzly;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import org.glassfish.grizzly.http.server.HttpServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class MyResourceTest {
private HttpServer server;
private WebTarget target;
#Before
public void setUp() throws Exception {
// start the server
server = Main.startServer();
// create the client
Client c = ClientBuilder.newClient();
// uncomment the following line if you want to enable
// support for JSON in the client (you also have to uncomment
// dependency on jersey-media-json module in pom.xml and Main.startServer())
// --
// c.configuration().enable(new org.glassfish.jersey.media.json.JsonJaxbFeature());
target = c.target(Main.BASE_URI);
}
#After
public void tearDown() throws Exception {
server.stop();
}
/**
* Test to see that the message "Got it!" is sent in the response.
*/
#Test
public void testGetIt() {
String responseMsg = target.path("myresource").request().get(String.class);
assertEquals("Got it!", responseMsg);
}
}
pom.xml - I added the jersey-media-json-jackson and the maven-assembly-plugin myself, so that you can create a single runnable jar file.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.underdog</groupId>
<artifactId>jersey-grizzly</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>jersey-grizzly</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.underdog.jersey.grizzly.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>create-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.underdog.jersey.grizzly.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jersey.version>2.17</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
With all the above, you can cd to the project from the command line and do
mvn clean package
java -jar target/jersey-grizzly-jar-with-dependencies.jar
and the application will start.
You can access it from http://localhost:8080/myapp/myresource
That's it. Note that the above is a normal jar project. So if you can't follow how to create the archetype, you can pretty much copy everything above into a jar project.
See Also:
Getting Started with Jersey Using Maven for some more explanation.
I can't comment the first answer. So I'm adding a comment here. If you choose to generate the project with the archetype, the command line should be
mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-grizzly2 -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false -DgroupId=com.underdog.jersey.grizzly -DartifactId=simple-service -Dpackage=com.underdog.jersey.grizzly -DarchetypeVersion=2.23.1
And not the command line in the link. This will work with the pom provided by peeskillet
Since your using Maven, hence you need to configure the properties to run on the Tomcat.
Right click on the Project -> Run as-> Run Configuration
Select the Maven Tomcat-> change the goals to 'tomcat:run'
Related
I have an App Engine project. Here is a sample repo, but it only contains a few files:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.happycoding</groupId>
<artifactId>google-cloud-hello-world</artifactId>
<version>1</version>
<packaging>war</packaging>
<properties>
<!-- App Engine currently supports Java 8 -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.9.71</version>
</plugin>
</plugins>
</build>
</project>
appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>MY_PROJECT_ID_HERE</application>
<version>1</version>
<threadsafe>false</threadsafe>
<sessions-enabled>true</sessions-enabled>
<runtime>java8</runtime>
</appengine-web-app>
HelloWorldServlet.java
package io.happycoding.servlets;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;");
response.getOutputStream().println("<h1>Hello world!</h1>");
}
}
I do not have a web.xml file because I'm using the #WebServlet annotation instead. This has worked perfectly for years.
The only problem was that I was restricted to using Java 8, so I was happy to see App Engine announce support for Java 11. I am now trying to upgrade my App Engine project to Java 11.
I started by changing the appengine-web.xml file to contain this line:
<runtime>java11</runtime>
I also changed the pom.xml file:
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
I run mvn appengine:devserver (which works fine before this change), and I get this error:
ClassLoader is jdk.internal.loader.ClassLoaders$AppClassLoader#78308db1, not a URLClassLoader.
I gather that this is because the App Engine Maven plugin itself requires Java 8. I also learn that the App Engine Maven plugin is deprecated, and that I should upgrade to the Cloud SDK Maven plugin. Okay fine.
I follow this guide and I change the plugin in my pom.xml file to this:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
</plugin>
I then run mvn package appengine:run (because of course the command to run a devserver changed too), but now I get this error:
java.io.FileNotFoundException: /home/kevin/gcloud-tutorials/hello-world/target/hello-world-1/WEB-INF/web.xml (No such file or directory)
The error says it can't find a web.xml file, but I shouldn't need one because I'm using the #WebServlet annotation! My pom.xml file also contains a <failOnMissingWebXml>false</failOnMissingWebXml> property, but I don't know whether that does anything with the new plugin.
Am I missing a step or property? How do I upgrade my App Engine project to use Java 11, without also requiring a web.xml file?
There are some pretty huge differences between App Engine's Java 8 runtime and its Java 11 runtime.
Specifically, the Java 8 runtime included a Jetty web server that automatically ran your code, but the Java 11 runtime no longer includes this, so you have to include it yourself.
There is a migration guide here but I found that very confusing to follow, so I'll try to outline the steps here:
Step 1: Migrate from appengine-web.xml to app.yaml.
Delete your appengine-web.xml file, and create a new app.yaml file. My app.yaml file only contained a single line:
runtime: java11
Step 2: Add a main entry point class that runs a web server.
There are many ways to do this, but there's what I did:
package io.happycoding;
import java.net.URL;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
/**
* Starts up the server, including a DefaultServlet that handles static files,
* and any servlet classes annotated with the #WebServlet annotation.
*/
public class ServerMain {
public static void main(String[] args) throws Exception {
// Create a server that listens on port 8080.
Server server = new Server(8080);
WebAppContext webAppContext = new WebAppContext();
server.setHandler(webAppContext);
// Load static content from inside the jar file.
URL webAppDir =
ServerMain.class.getClassLoader().getResource("META-INF/resources");
webAppContext.setResourceBase(webAppDir.toURI().toString());
// Enable annotations so the server sees classes annotated with #WebServlet.
webAppContext.setConfigurations(new Configuration[]{
new AnnotationConfiguration(),
new WebInfConfiguration(),
});
// Look for annotations in the classes directory (dev server) and in the
// jar file (live server)
webAppContext.setAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/target/classes/|.*\\.jar");
// Handle static resources, e.g. html files.
webAppContext.addServlet(DefaultServlet.class, "/");
// Start the server! 🚀
server.start();
System.out.println("Server started!");
// Keep the main thread alive while the server is running.
server.join();
}
}
This class uses Jetty to run a web server, and then adds the rest of your code to that web server. This code assumes that everything will be packaged in the same .jar file.
Step 3: Modify pom.xml
Your pom.xml needs a few things:
Dependencies for the web server you're running. I used Jetty.
Plugins for packaging your code. I chose to package mine as a single uber jar, so I used maven-resources-plugin and maven-shade-plugin.
Plugins for running your code locally. The old appengine-maven-plugin does not work for deploying locally, because it still requires appengine-web.xml for some reason. Because I chose the uber jar approach, I used exec-maven-plugin.
The appengine-maven-plugin does still work for deploying to the live server, so you still need it for that.
If that sounds confusing, you're right. But putting it all together, here's what I came up with:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.happycoding</groupId>
<artifactId>app-engine-hello-world</artifactId>
<version>1</version>
<properties>
<!-- App Engine currently supports Java 11 -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.version>9.4.31.v20200723</jetty.version>
<!-- Project-specific properties -->
<mainClass>io.happycoding.ServerMain</mainClass>
<googleCloudProjectId>YOUR_PROJECT_ID_HERE</googleCloudProjectId>
</properties>
<dependencies>
<!-- Java Servlets API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- Jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${jetty.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Copy static resources like html files into the output jar file. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-web-resources</id>
<phase>compile</phase>
<goals><goal>copy-resources</goal></goals>
<configuration>
<outputDirectory>
${project.build.directory}/classes/META-INF/resources
</outputDirectory>
<resources>
<resource><directory>./src/main/webapp</directory></resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Package everything into a single executable jar file. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${mainClass}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- Exec plugin for deploying the local server. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${mainClass}</mainClass>
</configuration>
</plugin>
<!-- App Engine plugin for deploying to the live site. -->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<projectId>${googleCloudProjectId}</projectId>
<version>1</version>
</configuration>
</plugin>
</plugins>
</build>
</project>
I put all of this into an example project available here.
I followed the steps on the page linked below to try and make an incredibly simple java web app using the embedded tomcat servlet.
https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat
Here is what I get in the shell after running webapp.
The server runs but then it doesnt show anything in the web browser. See this screenshot from the browser.
Here is a screenshot of my folder structure after packaging it with maven.
pom/xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.heroku.sample</groupId>
<artifactId>embeddedTomcatSample</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>embeddedTomcatSample Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<tomcat.version>9.0.16</tomcat.version>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper-el</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>${tomcat.version}</version>
</dependency>
</dependencies>
<build>
<finalName>embeddedTomcatSample</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>2.0.0</version>
<configuration>
<assembleDirectory>target</assembleDirectory>
<programs>
<program>
<mainClass>launch.Main</mainClass>
<name>webapp</name>
</program>
</programs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Launcher class:
package launch;
import java.io.File;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.DirResourceSet;
import org.apache.catalina.webresources.StandardRoot;
public class Main {
public static void main(String[] args) throws Exception {
String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
//The port that we should run on can be set into an environment variable
//Look for that variable and default to 8080 if it isn't there.
String webPort = System.getenv("PORT");
if(webPort == null || webPort.isEmpty()) {
webPort = "8080";
}
tomcat.setPort(Integer.valueOf(webPort));
StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
System.out.println("configuring app with basedir: " + new File("./" + webappDirLocation).getAbsolutePath());
// Declare an alternative location for your "WEB-INF/classes" dir
// Servlet 3.0 annotation will work
File additionWebInfClasses = new File("target/classes");
WebResourceRoot resources = new StandardRoot(ctx);
resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/classes",
additionWebInfClasses.getAbsolutePath(), "/"));
ctx.setResources(resources);
tomcat.start();
tomcat.getServer().await();
}
}
Servlet class:
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(
name = "MyServlet",
urlPatterns = {"/hello"}
)
public class HelloServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
ServletOutputStream out = resp.getOutputStream();
out.write("hello heroku".getBytes());
out.flush();
out.close();
}
}
I have tried this on Linux and Windows. I have also followed 2 other similar simple guides and got the same problem.
Can anyone please help me find where the issue is? Thank you very much.
hopefully my answer comes late, but I had apparently the same problem last night. I found the answer on SO:
It looks like you haven't added a Connector to your embedded server.
This was not necessary with tomcat 8, and therefore most of the sample code available doesn't mention this. Solution given worked for me. Just add the following line after the tomcat.setPort call:
tomcat.getConnector(); // Trigger the creation of the default connector
I am trying to access the clients IP that are calling my rest server but I only get null as a response. The web-server is running and I can access it from the web browser.
I have tried with
#Context HttpServletRequest
And also with
#Context ContainerRequest request
request.getRequestHeader("HTTP_FORWARDED")
//HTTP_X_FORWARDED
//HTTP_CLIENT_IP
But neither succeeds, the response is null or blank.
Setup
Jersey v: 2.22.2
Grizzly v: 2.3.22
Java v: 8
Rest.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
#Path("/rest")
public class Rest {
#GET
#Path("/test/")
#Produces(MediaType.APPLICATION_JSON)
public TestAddress test(#Context HttpServletRequest re){
System.out.println(re.getRemoteAddr());
TestAddress adr = new TestAddress();
adr.setAge(32);
adr.setName("Fidde");
adr.setSurename("Lass");
//System.out.println(uriInfo.getBaseUri());
return adr;
}
main.java
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.io.IOException;
import java.net.URI;
public class Main {
// Base URI the Grizzly HTTP server will listen on
public static final String BASE_URI = "http://localhost:8080/myapp/";
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
* #return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in com.example package
final ResourceConfig rc = new ResourceConfig().packages("com.example");
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
System.in.read();
server.stop();
}
}
Pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
Test
Bootstrap
jar
0.0.1-SNAPSHOT
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>backend.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
<properties>
<jersey.version>2.22.2</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
HttpServletRequest provides a getRemoteAddr() method that should returns the remote IP address.
Note that proxying or NATing may modify the IP address.
EDIT :
The solution is to inject a grizzly request :
#GET
#Path("/test/")
#Produces(MediaType.APPLICATION_JSON)
public TestAddress test(#Context org.glassfish.grizzly.http.server.Request re) {
System.out.println(re.getRemoteAddr());
...
}
This is working for me, but it is totally grizzly dependant.
I wanted to experiment with the WildFly AS. Created a very simple jax-ws example endpoint:
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.ejb.Stateless;
#WebService(serviceName = "HelloService")
#Stateless()
public class HelloService {
#WebMethod(operationName = "hello")
public String hello(#WebParam(name = "name") String txt) {
return "Hello " + txt + " !";
}
}
Tried to deploy it on server but got:
Cannot upload deployment: {"WFLYCTL0288: One or more services were unable to start due to one or more indirect dependencies not being available." => {"Services that were unable to start:" => ["jboss.deployment.unit.\"SoapTest-1.0-SNAPSHOT.war\".component.HelloService.CREATE","jboss.deployment.unit.\"SoapTest-1.0-SNAPSHOT.war\".component.HelloService.START","jboss.deployment.unit.\"SoapTest-1.0-SNAPSHOT.war\".component.HelloService.VIEW.\"com.mycompany.soaptest.HelloService\".SERVICE_ENDPOINT","jboss.deployment.unit.\"SoapTest-1.0-SNAPSHOT.war\".deploymentCompleteService","jboss.deployment.unit.\"SoapTest-1.0-SNAPSHOT.war\".moduleDeploymentRuntimeInformation","jboss.deployment.unit.\"SoapTest-1.0-SNAPSHOT.war\".moduleDeploymentRuntimeInformationStart","jboss.undertow.deployment.default-server.default-host.\"/SoapTest-1.0-SNAPSHOT\"","jboss.undertow.deployment.default-server.default-host.\"/SoapTest-1.0-SNAPSHOT\".UndertowDeploymentInfoService"],"Services that may be the cause:" => ["jboss.clustering.registry.ejb.default"]}}
Does WildFly need any special treatment to run such a simple code ?
I have deployed the same code on WebLogic 12.1.3 (with javaee 6 target) and the deployment run without any issues. Here is my project pom:
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>SoapTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SoapTest</name>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
Rémi Bantos - thanks for your suggestion. You have pointed me in the right direction. I was starting the server using: /opt/wildfly/bin/standalone.sh instead of using service mode /etc/init.d/wildfly start where important configuration options are set. I was thinking these failures might have something to do with the unusual platform (Debian/ARM - Raspberry Pi 2) at first but it was 100% my mistake. After setting up the config in /etc/default/wildfly the server started and both SOAP and REST examples deployed and worked properly. Thanks again Rémi!
Im trying to make an servlet extension to org.eclipse.equinox.http.registry.servlets extension point, but cant get it working. Ill try to write down my proccess so maybe someone can tell me what im doing wrong or what i didnt do :)
So, first i made just a jetty server with a default servlet.
Here was my initial pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>myserver</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<bundle.symbolicName>myserver</bundle.symbolicName>
<bundle.namespace>com.example</bundle.namespace>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>8.1.10.v20130312</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<manifestLocation>META-INF</manifestLocation>
<instructions>
<Bundle-SymbolicName>${bundle.symbolicName}</Bundle-SymbolicName>
<Bundle-Version>${pom.version}</Bundle-Version>
<Bundle-Activator>${bundle.namespace}.myserver.App</Bundle-Activator>
<Import-Package>
org.osgi.framework,
javax.servlet,
javax.servlet.http,
org.eclipse.jetty.server,
org.eclipse.jetty.servlet
</Import-Package>
<Require-Bundle>
</Require-Bundle>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
Here is my App thats a bundle activator:
package com.example.myserver;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class App implements BundleActivator {
public void start(BundleContext context) throws Exception {
Server server = new Server(8080);
ServletContextHandler c = new ServletContextHandler(server, "/");
c.addServlet(new ServletHolder(new HelloWorldServlet()),"/test");
server.start();
server.join();
}
public void stop(BundleContext context) throws Exception {
// TODO Auto-generated method stub
}
}
And here is my servlet:
package com.example.myserver;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloWorldServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Hello from HelloWorldServlet");
}
}
Then i launch my configuration with following bundles:
javax.servlet,
org.apache.felix.gogo.command,
org.apache.felix.gogo.runtime,
org.apache.felix.gogo.shell,
org.eclipse.equinox.console,
org.eclipse.jetty.continuation,
org.eclipse.jetty.http,
org.eclipse.jetty.io,
org.eclipse.jetty.security,
org.eclipse.jetty.server,
org.eclipse.jetty.servlet,
org.eclipse.jetty.util,
org.eclipse.osgi
Now when i type in url http://localhost:8080/test then everything works fine and my hello text appears.
Now i try to do the same thing with an extension of org.eclipse.equinox.http.registry.servlets.
Here is what i do:
1) Add org.eclipse.equinox.http.registry to Require-Bundle under pom.xml
2) open manifest, select extensions tab, click add, select org.eclipse.equinox.http.registry.servlets extension point, add, under extension details put class com.example.myserver.HelloWorldServlet and /test2 as alias.
Following plugin.xml is generated:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
point="org.eclipse.equinox.http.registry.servlets">
<servlet
alias="/test2"
class="com.example.myserver.HelloWorldServlet">
</servlet>
</extension>
</plugin>
Under launch configuration I needed to add these bundles:
org.eclipse.equinox.http.registry
org.eclipse.osgi.service,
org.eclipse.osgi.services,
org.eclipse.equinox.common,
org.eclipse.equinox.registry,
javax.xml
Then when i run my configuration i get a warning: !MESSAGE The extensions and extension-points from the bundle "myserver" are ignored. The bundle is not marked as singleton.
... so in pom.xml i change to this:
<Bundle-SymbolicName>${bundle.symbolicName};singleton:=true</Bundle-SymbolicName>
... run again, no errors, everything seems nice.
If i run http://localhost:8080/test everything works.
If i run http://localhost:8080/test1 i get an not found error.
Maybe i left something undone?
I hope i didnt go into too much detail, but i really hope someone can help me figure this out. Thanks! :)
You misplaced, because described alias="/test2", and
try with http://localhost:8080/test1
You should use http://localhost:8080/test2