I try to run a Jersey(1.17) resource on a Grizzly(2.2.21) server using HTTPS and Basic Auth and get everything working except the resource.
#Path("/")
public class Helloworld {
#GET
public String helloworld2() {
return "asdf2";
}
#Path("helloworld")
#GET
public String helloworld() {
return "asdf";
}
}
Yea it's just the Helloworld example and it still freaks me out.
I can access localhost:port/ and it works fine, but localhost:port/somethingother also returns "asdf2". Especially localhost:port/helloworld also returns "asdf2".
I also tryed
#Path("/")
public class Helloworld {
#GET
#Path("/helloworld")
public String helloworld() {
return "asdf";
}
}
and
#Path("/helloworld")
public class Helloworld {
#GET
public String helloworld() {
return "asdf";
}
}
In both cases i get 404 in Firebug for every request.
Does someone has a solution?
Thx
Edit:
To create the server and so on i use this example code (without the server truststore):
https://svn.java.net/svn/jersey~svn/trunk/jersey/samples/https-clientserver-grizzly/src/main/java/com/sun/jersey/samples/https_grizzly/
adding registration.addMapping("/*"); to my initialization code worked.
Thanks ver much alexey
Related
I am trying to provide endpoints that will listen on multiple versions, i.e /v1/test and /v2/test. In order not to duplicate my code, I use jersey's ability to use patterns in the #Path annotation.
Let's assume I want to provide a GET and a POST endpoint:
#Controller
#Slf4j
#Path("/")
public class TestController {
#GET
#Path("/v{version:[12]}/test")
#Produces(MediaType.APPLICATION_JSON)
public String test1(#PathParam("version") String version) {
System.out.println(String.format("GET /v%s/test called", version));
return "{\"foo\":\"bar\"}";
}
#POST
#Path("/v{version:[12]}/test")
#Produces(MediaType.APPLICATION_JSON)
public String test2(#PathParam("version") String version) {
System.out.println(String.format("POST /v%s/test called", version));
return "{\"foo\":\"bar\"}";
}
}
That works fine.
If I, however, try to use a specific path for the GET endpoints and use a pattern for the POST endpoint, I run into trouble.
Here the controller that would not work:
#Controller
#Slf4j
#Path("/")
public class TestController {
#GET
#Path("/v1/test")
#Produces(MediaType.APPLICATION_JSON)
public String test1() {
System.out.println("GET /v1/test called");
return "{\"foo\":\"bar1\"}";
}
#GET
#Path("/v2/test")
#Produces(MediaType.APPLICATION_JSON)
public String test2() {
System.out.println("GET /v2/test called");
return "{\"foo\":\"bar2\"}";
}
#POST
#Path("/v{version:[12]}/test")
#Produces(MediaType.APPLICATION_JSON)
public String test3(#PathParam("version") String version) {
System.out.println(String.format("POST /v%s/test called", version));
return "{\"foo\":\"barPOST\"}";
}
}
Doing GET /v1/test or GET /v2/test works fine, POST /v1/test however does not.
I get a 405 Method Not Allowed Exception.
As far as I got it the exception is thrown in the MethodSelectingRouter when it recognizes the path, but cannot find a method with the appropriate HTTP verb.
The issue seems to be that it picks the most specific path (/v1/test in my case) for which it does not know the POST verb.
Does anybody have an idea how to avoid this problem?
Cheers
PS: I am using spring boot with jersey (i.e. spring-boot-starter-web and spring-boot-starter-jersey) in version 1.5.2.RELEASE
I am trying a simple spring boot application. Here is my code. So when I run it is calling sayHello() why?
#RestController
public class HelloController {
#RequestMapping()
public String sayHello2(){
return "Hello2";
}
#RequestMapping(produces = { "text/html" })
public String sayHello(){
return "Hello";
}
}
It depends from where you are calling the api. When you call from browser where default format is text/html hence it calls sayHello. Try calling using curl, it will call sayHello2
It depends on your request header. If the request header has Accept text/html (usually from browsers), the corresponding request is executed. As #pvpkiran pointed out, try curl or alter the Accept header to see differences.
You are not providing the URL pattern both the method is sharing same
mapping as you have not mentioned over there i.e. "/".
#RestController
public class HelloController {
#RequestMapping(value="/")
public String sayHello2(){
return "Hello2";
}
#RequestMapping(value="/hello",produces = { "text/html" })
public String sayHello(){
return "Hello";
}
}
now when u enter / it will execute sayHello2(),and when URL pattern is /hello it will execute sayHello().
Please help me guys I'm going insane here..
So I was trying to use jersey (2.22.1) in an embedded jetty (9.2.14.v20151106), with the very simple main app like this:
public class MainApp{
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "etc.mypackage");
sh.setInitParameter(ServerProperties.PROVIDER_SCANNING_RECURSIVE, "true");
sh.setInitParameter(ServerProperties.TRACING, "ALL");
sh.setInitParameter("jersey.config.server.tracing", "ALL");
sh.setInitOrder(1);
sh.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
context.addServlet(sh, "/");
server.start();
server.join();
}
}
One of the thing that is not working here is that the jersey tracing doesn't seem to be working even if I set it in the parameter.
And I have 2 servlets at etc.mypackage.servlets :
#Path("/")
public class TestServlet {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String testString){ return "TestServlet.class; }
#Path("test1")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getString(){
String test = "TestServlet.class second method called";
return test;
}
}
and the other with identical functions but with different path and debug string :
#Path("/2")
public class TestServlet2 {
#Path("/test1")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String testString){ return "TestServlet2.class; }
#Path("test2")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getString(){
String test = "TestServlet2.class second method called";
return test;
}
}
These codes run and if called it in http://localhost:8080/ it will return a plain text TestClass.class from the first method of that class, but if I added any more path in the link, it will just return the same string, and no way I could invoke for it to display the second method of TestServlet class or TestServlet2.
But if changed the path from TestServlet from #Path("/") into anything other than that, it will just return error 404 for any URL including the http://localhost:8080/. I tried everything that I can think of the causes to but no avail, and it's so frustrating. Am I missing something here?
Thanks...
Here context.addServlet(sh, "/"); you are telling what path to match for access to the servlet. So the only access point you have is /. if you want access to "anything after /", you should add the wildcard *. So just change it to .addServlet(sh, "/*");
EDIT: I have a not-thoroughly-tested answer below from a colleague, but I would still like to hear discussion and better answers.
I'll be happy to be pointed to an answer, but I haven't found it with my searches.
Java REST can be implemented with annotations of classes and methods, including #Path annotation to match URIs. Is there an annotation, or other method, to match anything not explicitly matched by another annotation. An example:
#Path("")
public class RestEntryPoint {
#GET
#Path("/{s:.*}")
#Produces(MediaType.TEXT_PLAIN)
public String anything(#Context UriInfo ui) {
return "anything at all..." + ui.getPath();
}
#GET
#Path("/restserver/heartbeat")
#Produces(MediaType.TEXT_PLAIN)
public String heartbeat() {
return "Jetty RestServer heartbeat";
}
}
http://localhost:8082/restserver/heartbeat/
... returns the correct text in a browser ("Jetty RestServer heartbeat"). But I want any other URI to respond with the message from the method anything(#Context UriInfo ui) - however I only receive a 404.
If this can be done some other way, please tell me how. If this can be done this way (but differently) please show me the changes.
I think you need to map it to "/" explicitly and then let the method listen to ".*" or ".+":
#Path("/")
public class RestEntryPoint {
#GET
#Path("s:.*")
#Produces(MediaType.TEXT_PLAIN)
public String anything(#Context UriInfo ui) {
return "anything at all..." + ui.getPath();
}
#GET
#Path("restserver/heartbeat")
#Produces(MediaType.TEXT_PLAIN)
public String heartbeat() {
return "Jetty RestServer heartbeat";
}
}
This should do the trick.
just add a slash into the path.
like this
#Path("/")
public class RestEntryPoint {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String anything(#Context UriInfo ui) {
return "anything at all..." + ui.getPath();
}
#GET
#Path("/restserver/heartbeat")
#Produces(MediaType.TEXT_PLAIN)
public String heartbeat() {
return "Jetty RestServer heartbeat";
}
}
I'm new with Jersey Rest Framework and I wrote an simple demo to learn this skill. Here is my problem: I tried to reach my helloworld with this URL---
http://localhost:8080/PayInterface/query/helloworld
but didn't work. Would you please tell me what I did wrong?
I wrote a class:
#Component
//Declaring that all it will handle all requests starting by /TestCaseDto
#Path("query")
public class QueryApi {
#Path("/helloworld")
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public String test(){
return new String("Hello World!!!");
}
}
and I
A little more detail about this "dint work" would be nice
for starters- try changing your path above your class name like this
#Path("/query")
I think in here you return string. so you can't give produce type as xml,Try this
#Stateless
#Path("query")
public class QueryApi {
#Path("/helloworld")
#GET
#Produces({MediaType.APPLICATION_JSON})
public String test(){
return new String("Hello World!!!");
}
}