JAX-RS Resource not found in GlassFish Server - java

I've been trying to create a simple Restful WebService, using NetBeans Ide.
My Java EE Version is: Java EE 7 Web.
I created a new Java Web Application, setting this ContexPath: /DukesAgeService.
Now, running my application, browser display my Index.html page at:
http://localhost:8080/DukesAgeService/
so, everything works fine.
Then, I tried to create a simple restful resource using the RESTful Web Service Wizard.
So, I created this class:
package firstcup.webservice;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
/**
* REST Web Service
*
* #author nolanof
*/
#Path("dukesAge")
public class DukesAgeResource {
#Context
private UriInfo context;
/**
* Creates a new instance of DukesAgeResource
*/
public DukesAgeResource() {
}
/**
* Retrieves representation of an instance of firstcup.webservice.DukesAgeResource
* #return an instance of java.lang.String
*/
#GET
#Produces("text/plain")
public String getText() {
return "hello world";
}
}
But running my application, at url:
http://localhost:8080/DukesAgeService/dukesAge
I get a 404-not found page.
I exptected that any incoming get request that has the url of "/dukesAge" was handled by DukesAgeResource class getText method. Whats' wrong?
Thanks

You're probably missing the JAX-RS application servlet. You can either define it in the web.xml or if you want to go xml-less, you can use an Application subclass. The easiest way IMO is just to use the Application subclass annotated with #ApplicationPath. A servlet will be created and the servlet path will be set to the value in the annotation. Something like
#ApplicationPath("/rest")
public class RestApplication extends Application {
// All request scoped resources and providers
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(DukesAgeResource.class);
return classes;
}
// all singleton resources and providers
#Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<>();
return singletons;
}
}
Then the resource should be accessed via
http://localhost:8080/DukesAgeService/rest/dukesAge.
There are other ways, but this is the portable way. Glassfish uses Jersey, but creating a Java EE web application from scratch in Netbeans will only import compile time Java EE standard classes (no Jersey dependencies). So the above is really your best bet to start off with.
You can see other deployment options at the Jersey Documentation. For some of the options, you may need to add some Jersey compile-time dependencies. That's why I just mentioned the above. No other jars needed.
Another thing that would cause a 404, is if you specify the JAX-RS servlet path as /*. This will conflict with the default servlet that serves the static resources like your html pages. That's why I set it to /rest.
UPDATE
It is also stated in the JAX-RS spec that if there are empty sets returned in the getClasses() and getSingletons(), implicit classpath scanning should occur. (provider) Classes annotated withe #Provider will by default be added as singletons and resource classes annotated with #Path will be per-request objects (meaning a new object is created each request). So you could alternatively just have
#ApplicationPath("/rest")
public class RestApplication extends Application {
// Left empty
}
and it should work just the same.

You may have initialized some path in your web.xml, probably that is why you are getting a 404 error while you call the service. Do check your web.xml and in case it is set to anything rather then * then please append that to your service call to get it working.

Related

#RolesAllowed etc. without web.xml

I am currently working on a quite modular application where we have many jars that will be packaged and glued together in a war file.
Some of these jar files have REST resources that want to be secured. Common way is the #RolesAllowed annotation etc.
From my current knowledge this implies an existing web.xml in the WAR. This way we would have to implement jar-specific information (e.g. context roots) inside the WAR, not in the place where it belongs.
Like the most things nowadays - is there a way to programmatically set up security contexts etc. without a web.xml?
You can restrict access to your REST resources by registering RolesAllowedDynamicFeature in your REST configuration class that extends from ResourceConfig
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
super(ApplicationConfig.class);
register(RolesAllowedDynamicFeature.class);
}
}
So you can use your application roles on your resources methods like this
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
#Path("secured")
#PermitAll
public class SecuredResource {
#GET
#Path("user")
#RolesAllowed("user")
public String user(#Context SecurityContext sc) {
boolean test = sc.isUserInRole("user");
return (test) ? "true": "false";
}
#GET
#Path("admin")
#RolesAllowed("admin")
public String admin(#Context SecurityContext sc) {
boolean test = sc.isUserInRole("admin");
return (test) ? "true": "false";
}
}
Jersey documentation has more details on securing REST resources using annotations here
https://jersey.github.io/documentation/latest/security.html#d0e12428
I've not worked with JAX-RS for a while, but the last time I checked, when using annotation-based security, web.xml is not optional.
See my answer for details.
https://stackoverflow.com/a/20023018/839733

What is that Application class lifecycle of a rest service?

Is every rest service starting with extending that application class and defining applicationpath? What is the lifecyce of that application class itself? Here is an example:
import javax.ws.rs.core.Application;
#javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends Application {}
Is this a servlet? Is it always alive? How shall I understand this class? Is it a cdi bean? Does the server creates this class on every request?
What is Application?
Application is a deployment agnostic abstract class provided by JAX-RS for configuring and registering the components of a JAX-RS application and it's also used to supply additional metadata to the application.
Application is one of the types that can be injected using the #Context annotation. For more details, refer to this answer.
Subclasses of Application
Application subclasses can implement methods such as getClasses(), getSingletons() and getProperties() for configuring and registering components and properties.
Application subclasses can be annotated with #ApplicationPath, defining the base URI for the JAX-RS resource classes (classes annotated with #Path). Application subclasses are instantied once when the web application starts and they are managed by the JAX-RS runtime.
The simplest implementation possible is as following:
#ApplicationPath("api")
public SampleApplication extends Application {
}
In the example above no resources classes or providers are registered, so the JAX-RS runtime will scan the classpath for JAX-RS components and will register them automatically.
However, according to this post from Jakub Podlesak, this approach is discouraged in production environments:
The above example works great. When started, the application just scans the actual class-path, and adds every single JAX-RS component class found there to the actual runtime configuration. Isn't is great? Frankly, this kind of configuration could work just fine. Until someone changes either the system configuration (system class-path) or the way how you application is being packaged (a new 3rd party component could be added/removed from the application class-path then). These changes could be out of your control and if one of them happens, you application configuration could break. For this reason, it is not wise to use this kind of configuration in a production environment.
Jersey, the JAX-RS reference implementation, provides the ResourceConfig class. Compared to Application, ResourceConfig provides advanced capabilities to simplify registration of JAX-RS components, such as scanning for root resource and provider classes in a provided classpath or a in a set of package names, etc. For more details, refer to the Jersey documentation.
Working with multiple Application subclasses
Is also worth mentioning that you are not restricted to a single Application subclass per web application. The same WAR can have multiple Application subclasses. For more details, have a look at this post from Adam Bien:
To deploy multiple JAX-RS applications with different URIs in one WAR you will have to create one javax.ws.rs.core.Application subclass per such an application (or use web.xml for this purpose). Obviously the in Java EE ubiquitous Convention over Configuration (or Configuration by Exception) cannot work any more: you will have to explicitly configure resources in each subclass by overriding the method getClasses or getSingletons:
#Path("first")
public class FirstResource {
#GET
public String first() {
return "first";
}
}
#ApplicationPath("one")
public class JAXRSConfigurationOne extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>();
resources.add(FirstResource.class);
return resources;
}
}
#Path("second")
public class SecondResource {
#GET
public String first() {
return "second";
}
}
#ApplicationPath("two")
public class JAXRSConfigurationTwo extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>();
resources.add(SecondResource.class);
return resources;
}
}
Both JAX-RS applications become accessible through distinct URIs: http://localhost:8080/multiple-roots/one/first and http://localhost:8080/multiple-roots/two/second
What if no Application subclass is present?
If no Application subclass is present, the JAX-RS implementations are required to add a servlet and set its name to javax.ws.rs.Application and to automatically discover all resource classes and providers which must be packaged with the application.
For further details, have a look at the chapter 2 of the JAX-RS 2.1 specification.

in jersey 2.x am getting the error like java.util.concurrent.ExecutionException

i have used the jersey implementation of a jaxrs but iam unable to the programme following is case where i am getting problem any idea help me
in following programme i used the jersy 2.x implementaion of jaxrs
i implemented the programme using jersey implemetation of jax-rs(restfull)
2 classes i have written instead of web.xml i used the class
MyResource.java
package com.rest.application;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import com.rest.webservice.SampleService;
#ApplicationPath("rest")
public class MyResource {
private Set s;
public MyResource() {
s=new HashSet();
s.add(new SampleService());
}
public Set getSingletons() {
return s;
}
}
SampleService.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
#Path("sample")
public class SampleService {
#GET
#Produces("text/html")
#Path("{username}")
public String sayHello(#PathParam("username")String s) {
return "<font color='blue' size=8>Hello:" +s+ "</font>";
}
#GET
#Produces("text/plain")
public String sayBye() {
return "Bye";
}
}
i added the all jars needed to this programm
still i am getting following error
java.util.concurrent.ExecutionException:
org.apache.catalina.LifecycleException:
Failed to start component [StandardEngine[Catalina].
StandardHost[localhost].StandardContext[/RestApp2]]
Caused by: org.apache.catalina.LifecycleException:
Failed to start component [StandardEngine[Catalina].
StandardHost[localhost].StandardContext[/RestApp2]]
like this same error is displaying everywhere
when i changed the server tomcat 7 to 6
it is working but not displaying the output
will anybody have any idea thanking you in advance
This says, #ApplicationPath("rest") may be applied only to the subclass of Application.
Can you share more on what are you trying to do and what is the complete stack trace. Are you using web.xml ?
As #MSD mentioned, your use of #ApplicationPath is incorrect. See the Jersey documentation on Application Deployment to see all the different deployment options, and how they work in different environments.
Basically, the easiest way put the #ApplicationPath on an empty Application class
#ApplicationPath("/rest")
public class MyApplication extends Application {}
This will scan the entire classpath for #Provider and #Path annotated classes, to register with the application. Though this may seem easier, the more common approach, when working with Jersey is to use it's ResourceConfig class, which is a subclass of Application. You can register packages, which will scan the packages and subpackages
#ApplicationPath("/rest")
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("com.my.packages");
}
}
One benefit is that sometimes there will be third party dependencies that are annotated, but you don't want registered. To register individual classes just use register(...class) in the ResourceConfig.
Now the reason for the error in Tomcat 7 and not 6, is most likely because Tomcat 6 (servlet 2.5) does not have the sevlet pluggability mechanism, which uses the ServletContainerInitializer. The Jersey implementation of this initializer loads the application, looking for the #ApplicationPath on the Application subclass. If you're not in a 3.0 environment, this functionality will not work.
Note the Jersey initializer is included in the jersey-container-servlet jar. You can read more about it here

How do paths work in a Java deployed REST web service?

Under Tomcat and Jersey libraries I created a REST web service described in this class:
package Servicios;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
#Path("service")
public class ServiceResource {
#Context
private UriInfo context;
/**
* Creates a new instance of ServiceResource
*/
public ServiceResource() {
}
#GET
#Produces("text/html")
public String getHtml() {
return "<h1>Here we are, at the contemplation of the most simple web service</h1>";
}
#PUT
#Consumes("text/html")
public void putHtml(String content) {
}
}
So, as I set it before accessing to http://localhost:8080/GetSomeRest makes the default created .jsp file created.
I set in project propierties (using NetBeans) a relative URL as webresources/service, so service part is same defined in #Path("service"). All works ok, going to http://localhost:8080/GetSomeRest/webresources/service makes the web service be consumed.
But what if I want to consume that service right from http://localhost:8080/GetSomeRest/service? I tried to set only service in such relative URL and I got an Error 404 message going to http://localhost:8080/GetSomeRest/service
How do virtual paths work?
What would it mean to add an alias to a web service?
The path segment webresources is not set in the code you provide so I will guess what your code looks like.
A JAX-RS application can be configured with a class extending javax.ws.rs.core.Application. Such a class can be annotated with #javax.ws.rs.ApplicationPath(). My guess is that in your project this annotation is set to
#javax.ws.rs.ApplicationPath("webresources")
So the URL of a JAX-RS resource class is build from these parts.
http://localhost:8080/ - host and port
GetSomeRest - the context, normally the name of the deployed .war file
webresources - the value of the #ApplicationPath annotation
service - the value of the #Path annotation of the class
I recommend not to skip step 3.
The value of the #ApplicationPath annotation can be overridden by a servlet-mapping element in the web.xml.
Just for information
The path segment webresources
is set in the code by netbeans in the package
org.netbeans.rest.application.config - ApplicationConfig Class into your own project!!! so change it and it's done...

OSGi component configurable via Apache Felix

I'm a complete newb at this so I apologize in advance. I'm trying to create
an OSGi component that simply shows a hello world message and is configurable via the input from felix. Then spits it out on a jsp page. I'm using scr annotations to help do this. Here is my java code
package com.training.cq5.trainingApp;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.apache.sling.commons.osgi.PropertiesUtil;
#Component(label= "Welcome Message",
description = "Welcome Message for the training excercise",
immediate = true, enabled = true, metatype=true)
#Properties({
#Property(name = "welcome.message", value = "WelcomeMessage")
})
#Service(WelcomeMessage.class)
public class WelcomeMessage {
private static String welcome_message = "Welcome";
#Activate
protected void activate(ComponentContext ctx) {
welcome_message = PropertiesUtil.toString(ctx.getProperties().get(welcome_message), welcome_message);
}
public static String getMessage() {
return welcome_message;
}
}
Here is were I am calling it in the JSP:
<%# page import="com.training.cq5.trainingApp.WelcomeMessage" %>
<h2><%= WelcomeMessage.getMessage() %></h2>
Is there any reason why it's not updating from felix? All I'm getting is the "Welcome"
text from the welcome_message string.
You are accessing WelcomeMessage.getMessage() as a static method, but what you want is the actual service. When you annotate a class with the #Service and #Component annotation, you indicate to the OSGI framework that you want an instance of this class registered as a service. This service instance is managed by the OSGI framework, in terms of its lifecycle (when its instantiated) or through which classloader the appropriate classes are loaded.
However in order to use the #Component and #Service annotations, you'll have to use the Apache Felix SCR plugin. Once that works, your service will be instantiated.
Then you'll have to access the service. The easiest way in Sling, which you appear to be using, is SlingScriptHelper.getService() which lets you lookup a service.
Update
In OSGI services are registered by their type. When you declare a service with #Service(MyClass.class), the service will be registered under the type MyClass. To retrieve it you would query the service registry for a service of the given type. In Java code you'd be using either getServiceReference(Class clazz)/getService(ServiceReference reference) the #Reference annotation.
In a JSP on a Sling system you can use the SlingScriptHelper, as outlined earlier. Here's a short code sample (assuming correct imports):
<%
SlingBindings bindings = (SlingBindings) req.getAttribute(SlingBindings.class.getName());
SlingScriptHelper scriptHelper = bindings.getSling();
MyService service = scriptHelper.getService(MyService.class);
// ... do stuff with service.
%>
If you are going to work more with OSGI, I highly recommend the OSGI specification. It's free to download and explains everything in great detail.
ilikeorangutans is correct that you don't want a static method on your OSGi service - the idea is that a service implements an interface, clients retrieve it from their OSGi context and use it via its service interface.
The Apache Sling webloader sample uses this technique to access a Webloader service in its request processing scripts. The scripts are ESP in this case (server-side javascript) but the principle is exactly the same with JSP.
The service interface is defined in Webloader.java, and WebLoaderImpl.java implements it as an OSGi service.
Then, the html.esp script gets the service using sling.getService:
var loader = sling.getService(Packages.org.apache.sling.samples.webloader.Webloader);
Change this line:-
welcome_message = PropertiesUtil.toString(ctx.getProperties().get(welcome_message), welcome_message);
to
welcome_message = PropertiesUtil.toString(ctx.getProperties().get("welcome.message"), welcome_message);
notice the difference :-ctx.getProperties().get(welcome_message) vs ctx.getProperties().get("welcome.message")

Categories

Resources