-
1. Re: Exposing a specific interface implementation as RESTFul web service.
emag Mar 15, 2016 7:08 AM (in response to mauriclaudio)IMO, I think it's preferable delegating injected service classes to several JAX-RS endpoint itself implementations.
import javax.inject.Inject; @Path("/some-api") public class SomeApi { @Inject private SomeBean someBean; // Via @javax.enterprise.inject.Produces @GET public String doSomething() { return someBean.doSomething(); } }
However, (though I'm not sure it's the best way), it works the following way. You can switch the specific implementation using System property at runtime.
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashSet; import java.util.Set; @ApplicationPath("/") public class RESTActivator extends Application { private Set<Object> singletons = new HashSet<>(); private Set<Class<?>> empty = new HashSet<>(); public RESTActivator() { boolean useSecond = Boolean.parseBoolean(System.getProperty("use.second", "false")); if (useSecond) { singletons.add(new SecondBean()); } else { singletons.add(new FirstBean()); } } @Override public Set<Class<?>> getClasses() { return empty; } @Override public Set<Object> getSingletons() { return singletons; } }
I created the sample repository.
GitHub - emag/jboss-developer-268492: https://developer.jboss.org/thread/268492
-
2. Re: Exposing a specific interface implementation as RESTFul web service.
mauriclaudio Mar 15, 2016 3:32 PM (in response to emag)Hi Yoshimasa,
first of all, thanks really a lot for your time and the code you shared on GitHub. It works really well, but I'm afraid you missed a detail: my question was about EJBs, not POJOs . With EJBs as far as I experimented using javax.ws.rs.core.Application getClasses() or getSingletons() methods to expose REST resource doesn't work. After reading in depth RestEasy documentation, eventually I found a way to achieve my goal - i.e, select which implementation to use when multiple implementations are available.
The key of mine solution is to use REST sub resources locators. First, let's define a business interface implemented by two ejbs:
package com.rest.test; import javax.ejb.Local; import javax.naming.InitialContext; import javax.ws.rs.GET; import javax.ws.rs.Path; @Local @Path("/commonrest") public interface CommonRestIntf { @Path("/processor") default public CommonRestIntf getProcessor() { try { InitialContext ctx = new InitialContext(); String actualJNDIName = ...; // select here somehow which ejb to use CommonRestIntf intf = (CommonRestIntf) ctx.lookup(actualJNDIName); return intf; } catch(Exception e) { return null; } } @GET @Path("/greetings") public String getGreetings(); }
Please note that I define a default implementation of the method getProcessor() that is responsable for locating and initializing the actual ejb I want to use. This method is annoted with @Path but misses any @GET, @POST annotations - as far as I understand this is the way that lets you to define a subresource locator method.
Hence, I defined two simple EJBs:
@Stateless public class FirstBean implements CommonRestIntf { public AlfaBean() { // TODO Auto-generated constructor stub } @Override public String getGreetings() { return "Returned by FirstBean"; } }
and
@Stateless public class SecondBean implements CommonRestIntf { public SecondBean() { // TODO Auto-generated constructor stub } @Override public String getGreetings() { return "Returned by SecondBean"; } }
As last step, I defined a Singleton EJB to initialize REST services:
@Singleton @Startup @ApplicationPath("/ejbrest") public class StarterREST extends Application { /** * Default constructor. */ public StarterREST() { // TODO Auto-generated constructor stub } }
To access RESTFul webservice, you may type in a browser : http://localhost:port/WebAppCTX/ejbrest/commonrest/processor/greetings.
Again, thanks so much for your help. I have really appreciated it.
All the best !