I am trying to build a very basic Restful server in Eclipse using jersey and GrizzlyHttpServerFactory. Below is the code:
The server
package com.example.rest;
class WebServr{
public static final String BASE_URI = "http://localhost:8080/myapp/";
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in com.example.rest package
final ResourceConfig rc = new ResourceConfig().packages("com.example.rest");
// 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);
}
public static void main( String[] args ) {
WebServr wb = new WebServr();
wb.startServer();
}
}
The rest component
package com.example.rest;
#Path("/amp")
#Produces("text/html")
public class Endpoint{
#GET
#Path("/test")
public Response test() {
return Response.ok().entity("SUCCESS").build();
}
}
But when I create a simple “jar” file by exporting my compiled java files using above code, I can see my server is running(can see output in netstat –an | grep port) but my restful client is returned with “404 error”(though I can see a new http connection is being established at server side).
But when I create a jar file using eclipse option of “Runnable jar”, it works perfectly fine(my client is served properly).
Can anyone give any suggestion why it is happening.
i am facing the same issue,
The short answer :
place your compiled classes in web-inf/classes
The long version :)
I am convinced that because of ClassLoader in tomcat, web-inf/classes is being loaded before web-inf/lib,
when you place your classes in web-inf/classes it's being loaded by classloader, then when web-inf/lib jars are loaded which jersey one of them, jersey will scan for the declared classes, and will find them (WIN)
BUT
when classes are in a jar file (in web-inf/lib) they will be loaded yes, but MOSTLY they are loaded after jersey, and as a result when jersey scans for the endpoints it will find nothing.
i know this question is a bit old, but this could help someone facing same issue.
For a solution, actually i am still looking, if i can control the order of jars loading, or i may implement some classes (Application, Configuration) from jersey and figure out a way to let jersey find them.
Related
I have an application which allows to dynamically generate web applications (wars) and I would like to deploy these applications in a server to test them and I think of putting them in the same embedded server of spring, here is how I solved the problem with a simple main java.
public class Main {
private final static Logger logger = LoggerFactory.getLogger(Main.class);
private final static File catalinaHome = new File(
"C:\\Users\\Dev\\Desktop\\demo\\userstory-2\\compiler\\patternHost");
private static Tomcat tomcat = null;
public static void main(String[] args) {
tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.setBaseDir(catalinaHome.getAbsolutePath());
tomcat.getHost().setAutoDeploy(true);
tomcat.getHost().setDeployOnStartup(true);
tomcat.getServer().addLifecycleListener(new VersionLoggerListener());
tomcat.getHost().addLifecycleListener(new HostConfig());
try {
tomcat.start();
} catch (LifecycleException e) {
logger.error("Tomcat could not be started.");
e.printStackTrace();
}
logger.info("Tomcat started on " + tomcat.getHost());
tomcat.getServer().await();
}
}
How can I do the same with spring boot. ?
I have converted a non-spring app to spring boot in this way and it worked for me. I was able to run it with spring boot embedded tomcat. Hope this helps.
Spring boot is all about speed, it comes with embedded-tomcat server(provided you use spring-boot-starter-web dependency) and now all you need is java to run your standalone spring boot application. It reduces the manual steps of copying war file to tomcat's webapp folder and then starting it.
Try the approach which suits your app.
If your old app is spring based :
Create a new spring boot starter web project and copy your old source code to this new project. Modify application.properties, resources folder, add all required dependencies in pom.xml file and change package as war.
Do a mvn clean install it will generate a war file (with embedded
tomcat) in target folder of your project's root directory. Now to run it all you
need to do is, in your target folder open terminal and run java -jar your_warFileName.war it will start the application.
If your old app is not a spring based:
Again start with new spring boot starter web project and copy your source code but then to use your old code with spring-boot, first you have to do clean-up stuff like adding #RestController to controller classes, declaring beans by marking classes with #Service or #Component and autowiring beans in the appropriate places. Once your code compiles fine then to run it your can use step 2 as above.
I've programmed a very simple chat JAX-RS application deployed with glassfish 4.1 in Netbeans with the following sources:
practica2/Message.java // entity from MySQL DataBase
practica2/service/AbstractFacade.java
ApplicationConfig.java
MessageFacadeREST.java // resource class
These source files are obtained executing Netbeans 'RESTful Web Services from Database' wizard against a MySQL database message with following attributes:
- id INT(11) flags: PK NN AI
- content VARCHAR(250) NN
- user_sender VARCHAR(45) NN
- date DATETIME NN
The services in MessageFacadeREST.java consist of two methods: create and retrieveFromDate:
#POST
#Override
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public void create(Message entity) {
super.create(entity);
}
#POST
#Path("from")
#Consumes({"application/xml","application/json"})
#Produces({"application/xml", "application/json"})
public List<Message> retrieveFromDate(Message message) {
// retrieves list of messages newer than message
}
Server works well and chat clients (mostly android) create and retrieve messages to/from the server.
Since my students have to complete retrieveFromDate I'd like to provide them with a binary MessageFacadeREST.class archive in a library. I prepare a server2 folder with:
server2/practica2/service/MessageFacadeREST.class
adding this folder as a library and eliminating corresponding .java from sources. Then it stops working. What I've noticed is that Netbeans no longer adds MessageFacadeREST.class in addRestResourceClasses() method. If I try to load it manually:
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
//addRestResourceClasses(resources);
resources.add(practica2.service.MessageFacadeREST.class);
return resources;
}
/**
* Do not modify addRestResourceClasses() method.
* It is automatically populated with
* all resources defined in the project.
* If required, comment out calling this method in getClasses().
*/
//private void addRestResourceClasses(Set<Class<?>> resources) {
//}
}
I get:
GlassFish Server (1), deploy, null, false
/home/francesc/NetBeansProjects/WebApplication1/nbproject/build-impl.xml:1049: The module has not been deployed.
See the server log for details.
BUILD FAILED (total time: 0 seconds)
Then the question is: how can I split a working JAX-RS application between sources and binary class libraries?
(SOLVED):
First of all, thanks to #John Ament and #OndrejM for their valuable comments. In my original post I had almost found the solution. Two points to take into account:
1.- When distributing resources as .class make sure to register to JAX-RS runtime: manual loading of MessageFacadeREST.class is mandatory.
2.- In Netbeans it seems that run option doesn't redeploy correctly ('The module has not been deployed' error). deploy option (instead of run) must be used
Now it works.
Netbeans probably deletes the .class files after you removed the sources from the project.
You have to copy the .class files into a folder where Netbeans searches for resource files.
In classical Netbeans Java Web project, that would be in WEB-INF folder, by default web/WEB-INF. You can also copy the classes to any other folder and add the folder as a Library, in Compile tab (In project properties dialog).
If the project is maven-based project, just copy the folder with classes into the src/main/resources folder.
I have a Dropwizard/AngularJS website. I have my assets served from an AssetsBundle on the root directory:
public void initialize(Bootstrap<WebsiteConfiguration> bootstrap) {
bootstrap.addBundle(new AssetsBundle("/assets/", "/", "index.html"));
...
}
And I want to serve my REST endpoints on /services:
public void run(WebsiteConfiguration configuration, Environment environment) throws Exception {
environment.jersey().setUrlPattern("/service");
...
}
Based on documentation and answers I've seen elsewhere, this seems like it should work. However, I just tried it, and everything on /service is returning a 404. When I dug into the app through a debugger, it appears that it's because the requests are going through the AssetServlet, not through Jersey.
Am I missing something? Is there a good way to serve my front-end on the root directory and the REST services on a sub-path?
I also struggled with this issue some time ago. What helped me was adding these lines to the app.yml config file:
server:
type: simple
rootPath: '/rest/*'
applicationContextPath: /
I have a simple project to test JAX-RS services. Yesterday I downloaded jersey-1.7.1 and used com.sun.jersey.api.container.httpserver.HttpServerFactory and com.sun.net.httpserver.HttpServer to create a http server to test my services from inside eclipse (w/o a heavy weight container)
Today, I downloaded the latest jersey jars (jaxrs-ri) and the HttpServerFactory is missing. Looks like they removed the class between 1.7.1 => 2.0 but I cannot find it in deprecated section. I see grizzly2 classes in API section (maybe that is what I am supposed to use now) but none of the jars in jaxrs-ri bundle provide those classes. I downloaded the jersey-grizzly 1.12 jar but it only has com/sun/jersey/server/impl/container/grizzly2/GrizzlyContainer classes and no implementation.
So question to kind souls
1 - with the latest jaxrs-ri jars from jersey download page, what is the recommended way to create a simple http server to test from command line if the 1.7.1 way has been deprecated.
what jars to download/include and perhaps a short code sample?
2 - The whole documentation around creating a simple REST service using java is a big mess. So how do you find the right information?
(Really, this is not a joke. maybe this would require a separate blog post - just look at the mess, changed API, no information on deprecated features, implementation diffs, e.g. CXF vs. jersey, API 1.x vs API 2.0, Glassfish container v x.y vs. Tomcat, version x of y vs. version x2 of y, servlet 3.0 would have this file, are you extending Application or not!)
Update
working example with JDKHttp server
package test.jersey;
import java.net.URI;
import com.sun.net.httpserver.HttpServer;
import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory ;
import org.glassfish.jersey.server.ResourceConfig;
public class ConsoleServerV2 {
static final String BASE_URI = "http://localhost:9099/";
public static void main(String[] args) throws Exception {
HttpServer server = null ;
ResourceConfig rc = new ResourceConfig(rest.Service.class);
URI endpoint = new URI(BASE_URI);
server = JdkHttpServerFactory.createHttpServer(endpoint,rc);
System.out.println("console v2.0 : Press Enter to stop the server. ");
System.in.read();
server.stop(0);
}
}
You could use the JdkHttpServerFactory, which is available in the jersey-container-jdk-http-2.0.jar:
ResourceConfig rc = new ResourceConfig(HelloWorldResource.class);
HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, rc);
No need to call server.start()!
Pls try this Grizzly 2 bundle
http://search.maven.org/remotecontent?filepath=org/glassfish/grizzly/grizzly-http-servlet-server/2.3.3/grizzly-http-servlet-server-2.3.3.jar
You can also get the bundle from here
http://mvnrepository.com/artifact/com.sun.jersey/jersey-server/1.2
Just add it to your library folder then right click on it in the project and select "Add as a library."
I have created two webservices clients in NetBeans 7.1, mimicking the tutorial they have on their website.
I had done the first one a while ago against a wsdl file located at a http location, and had no problem using the webservice
The webservice I am working with at the moment has a wsdl file located at a https location. The setup of the service went off without a hitch. The only difference with the first one was a popup alerting me to a security certificate, which I accepted. Service, Generated Sources, META-INF etc are all created successfully. A local copy of the wsdl file is stored on my pc under the src/.. folder.
However, as soon as I go to run my code, I receive this error:
Cannot find 'https://-domain-.net/-XYZServices-/-ABCXML?wsdl-'
wsdl. Place the resource correctly in the classpath.
I found several similar issues in Stackoverflow and other places online, but nothing that really addressed my problem. I tried several suggestions anyway:
I checked the jax-ws-catalog.xml file, and found the url quoted above mapped to the local folder where the local copy of the wsdl is stored.
I checked whether that local folder actually contained the wsdl file - it did.
I tried editing the url in the jax-ws-catalog.xml file to point to port 8080 and 8081 - no joy.
I guess it is a security issue, but have no clue as to how to fix this.
Can anyone point me in the right direction here.
FYI: I'm fairly new to java and NetBeans.
Thanks.
The best way to avoid the error "Cannot find wsdl. Place the resource correctly in the classpath." is to use wsdllocation to specify the location of the wsdl and also to package the wsdl as part of the jar.
When you specify the wsdllocation make sure you add "/" to the beginning of the location.
wsimport -keep -Xnocompile -wsdllocation /schema/10.0/MyService.wsdl schema/10.0/MyService.wsdl
Just put your WSDL file in your classpath, etc., src/main/resources/MyWsdl.xml and use this to get it:
URL url = new URL(baseUrl, "classpath:MyWsdl.xml");
Also do not forget to add this on your service class that extends javax.xml.ws.Service:
#WebServiceClient(name = "MyService", targetNamespace = "http://example.org/", wsdlLocation = "classpath:MyWsdl.xml")
Not sure if this helps, but...
From Here
On the client side to consume SSL enabled Web service:
- in the New Web Service Client wizard under WSDL and Client location specify the WSDL file of the Web Service by setting WSDL URL in form
of https://:8181//
- then right click on the created web service and choose Edit Web Service Attributes and under Wsimport Options correct the wsdlLocation
option to the following form:
/META-INF/wsdl/_8181//.wsdl
Whenever you refresh the web service a fresh wsdl file gets loaded
from the deployed application and the wsdl file gets loaded as a
resource defined by the correct path (mentioned wsdlLocation option
value).
Make sure that you have configured your web service.
One way to do so is to implement a class that extends javax.ws.rs.core.Application. That is, add a class which is similar to the following:
import java.util.Set;
import javax.ws.rs.core.Application;
#javax.ws.rs.ApplicationPath("rest")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(rest.HelloWorld.class);
resources.add(rest.Search.class);
// Here continue adding all the JAX-RS classes that you have
}
}