JavaEE6+REST: How do I get all REST resources at runtime? - java

Is there a possibility to get a list of all registered REST resources at runtime?
With REST resources I mean:
either classes which have annotations such as #Path(...) and are considered by the server at runtime (so traversing all classes using reflection would not do),
or URIs of all paths (REST class can have multiple paths).
NOTE 1: I am using automatic configuration (that new feature of JavaEE 6) and Netbeans just generates an empty ApplicationConfig class.
NOTE 2: Using Netbeans 6.9, JavaEE 6, Glassfish 3. Is more information on my ecosystem needed?

Are you using Jersey? If so, then a WADL is generated automatically at /application.wadl. The WADL contains a lot of information about registered resource paths.
See also: WADL Support

public synchronized Response doSomething(#Context Application c, #FormParam("someParam") String someParam)
throws Exception {
// gives a list of classes which are used by this Jersey instance
// and have REST-related annotations
c.getSingletons(); // returns Set<Object>
return something;
}

Related

New to REST - adding a web service class instance to a hashSet

I've been going through this tutorial and they added a web service class instance to a hashSet, like this:
public class MessageApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public MessageApplication() {
singletons.add(new MessageRestService());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
I do not understand what the purpose of it is... I thought you could just access the web service with a URL
You made a class, this class is able to handle web requests. But this class has to be hosted somewhere. This means, this class has to be activated by a URL route. In this case you're using JBOSS.
In the first option of the tutorial, MKyong shows you how to configure RESTEasy Bootstrap (a bootstrap to load references) to map the URL with your class. This is done in web.xml and configures some kind of scanner that will map a certain URL with your class.
The second option is not using RESTEasy Bootstrap and you have to add your class to a collection of long living objects in your application manually. This is done defining the Application (MessageAplication) and defining it in the web.xml.
Yes, you can access the webservice via a URL, but the server needs to know what to do with calls to a certain URL.
Yours is one way (the bootstrap version) of telling the application server where to look for JAX-RS resources: http://www.mastertheboss.com/resteasy/resteasy-tutorial (Step #4)
There is a (newer) alternative, depending on which server and RESTeasy-version you use, which relies on autoscanning for certain annotations. For RESTeasy on JBoss, it's described at the bottom of the tutorial-page I linked.

How do you configure a JAX-RS MessageBodyWriter on a per-request basis?

Essentially, I have a MessageBodyWriter that writes objects as JSON, and I'd like to be able to control some aspects of the output based on which resource method handled the request. However, the default lifecycle of #Provider classes is singleton (one per JVM), so I can't inject an instance of some configuration object. This leaves me with 2 obvious workarounds:
Use custom annotations: Each call to writeTo(...) includes the list of annotations on the method that was invoked, so I could check for the existence of some annotation. However, JAX-RS methods are already pretty laden with metaprogramming.
Use a ThreadLocal property map: Assuming one request per thread, but this approach breaks encapsulation a bit. The resource methods needs to be aware that there is some other class out there, looking for this map.
Is there a way to change the lifecycle of the Provider itself? I am using Jersey.
Not sure why you need a MessageBodyWriter Provider with per-request basis. If you just want to distinguish which methods are with JSON ouput and which are not, then jersey-json does already support.
And although the #Provider is singleton. You still can use per-request object within it like below.
#Provider
public class StViewProcessor implements ViewProcessor<ST> {
......
#Context
HttpServletRequest request;
public void writeTo(ST st, Viewable viewable, OutputStream out)
throws IOException {
System.out.println(request.getRequestURI());
...
}
}
And if you want to inject your instance per request, you can have a look at PerRequestTypeInjectableProvider. Here is a link about it.
The JAX-RS 1.1 spec requires that implementations support singleton providers and allows support for other lifecycles but doesn't suggest anything else along those lines. As far as I'm aware, pure Jersey doesn't support anything beyond singletons. With the jersey-spring contrib module, you get support for using Spring as Jersey's IoC container (where it gets its resource and provider instances from). I know Spring supports multiple lifecycles, including request, but I'm not sure if support for that is built into jersey-spring.

How to implement Soap Faults in Java webservices?

Am pretty new to web services and have been trying to implement Soap Faults. I used Apache Axis2 to generate webservice in the following manner.
public interface XYZ{
public String myMethod(User[] user)
}
Here I have created a User class with some variables so that I can generate User object at .Net environment to pass User[] of objects.
Public class Webservice implements XYZ
{
Public String myMethod(User[] user){
//My implementation
}
}
Now, I created a dynamic project using Eclipse and with the help of Axis2 plugin I created webservice for my "Webservice" class which generates wsdl file. I deployed the webcontent in the Tomcat folder and able to access the WSDL file in the .Net environment. I am able to pass array of objects (User[]) from .Net to Java and able to do my task. Now, I need to implement Soap Faults in Java which I am not sure how to implement.
Can anyone help me with an example or tutorial ?
Your best bet is to Google for something like "jax-ws faults". For example:
http://www.ibm.com/developerworks/webservices/library/ws-jaxws-faults/index.html
You can also implement an error handler, as discussed under "Using handlers in JAX-WS Web services" here:
http://axis.apache.org/axis2/java/core/docs/jaxws-guide.html#BottomUpService
Most frameworks will trigger a SOAP fault when you throw an Exception in the method implementing your operation. That will not give you much control on the SOAP fault content though.
See here for some details on Axis
Generally, You don't need any specific coding for implementing SOAP fault.. Whenever there is any exception thrown by the method (here myMethod in your example.), axis will automatically generate SOAPFault element in the resulting response. The exception is actually wrapped into AxisFault exception and sent to the client.
See here a i.

Using MessageBodyReader for multiple parameters in RESTful services

The following method does not allow my servlet container to start:
#PUT
public String upload(final Customer customer, final Control control) {
// ...
}
I get, not surprisingly:
SEVERE: Missing dependency for method ... at index 0
SEVERE: Missing dependency for method ... index 1
SEVERE: Method, ..., is not recognized as valid resource method.
I have implemented MessageBodyReaders for each type. Removing any of the parameters enables the servlet container to start gracefully, so I suspect there must be a restriction on the number of parameters that will be resolved via Entity-Providers.
The problem is that I NEED these two parameters, since I am providing both SOAP and REST support, and of course, I am not in the liberty of changing method signatures, and I also do not want to create one specific Jersey method and one specific JAX-WS method as entry points.
I'm using Jersey 1.7.
JAX-RS allows only one entity parameter. The reson is very simple: each request may have at most one body (multiparts are not supported by spec)
So you must create two methods.
Btw, I don't think it's a good practice to mix JAXRS and JAXWS in the same class.

java ee | ejb3 | runtime dispatch

I would like to call an ejb3 at runtime. The name of the ejb and the method name will only be available at runtime, so I cannot include any remote interfaces at compile time.
String bean = 'some/Bean';
String meth = 'doStuff';
//lookup the bean
Object remoteInterface = (Object) new InitialContext().lookup(bean);
//search the method ..
// foreach (methods)
// if method == meth, method.invoke(bean);
the beans should be distributed accross multiple application servers, and all beans are to be called remotely.
Any hints? specifically i do not want:
dependency injection
inclusion of appliation specific ejb interfaces in the dispatcher (above)
webservices, thats like throwing out processing power for nothing, all the xml crap
Is it possible to load an ejb3 remote interface over the network (if yes, how?), so I could cache the interface in some hashmap or something.
I have a solution with a remote dispatcher bean, which I can include in the above main dispatcher, which does essentially the same, but just relays the call to a local ejb (which I can lookup how? naming lookup fails). Given the remote dispatcher bean, I can use dependency injection.
thanks for any help
(netbeans and glassfish btw)
ejb3 calls use RMI. RMI supports remote class loading, so i'd suggest looking into that.
also, JMX mbeans support fully untyped, remote invocations. so, if you could use mbeans instead of session beans, that could work. (JBoss, for instance, supports ejb3-like mbeans with some custom annotations).
lastly, many app servers support CORBA invocations, and CORBA supports untyped method invocations.
You might be able to use java.rmi.server.RMIClassLoader for the remote class loading. You'll also need to load any classes that the remote service returns or throws.
It cannot be done. You will always get a "class not found" exception. That is in my opinion the biggest disadvantage of EJB/Java. You loose some of the dynamcis, because the meta-language features are limited.
EJB3 supports RMI/IIOP, but not RMI/JRMP (standard RMI) so dynamic class loading is not supported.You loose some Java generality, but gain other features like being able to communicate about transactions and security.
You need to use reflection for this, and it is very simple to do. Assuming that you're looking for a void method called meth:
Object ejb = ctx.lookup(bean);
for (Method m : ejb.getClass().getMethods()) {
if (m.getName().equals(meth) && m.getParameterTypes().length == 0) {
m.invoke(service);
}
}
If you're looking for a specific method signature just modify the m.getParameterTypes() test accordingly, e.g. for a method with a single String parameter you can try:
Arrays.equals(m.getParameterTypes(), new Class[]{String.class})
And then pass an Object[] array with the actual arguments to the m.invoke() call:
m.invoke(service, new Object[]{"arg0"})

Categories