With RESTEasy I've implemen开发者_StackOverflow中文版ted a subclass of Application to provide a list of singleton resources. Is there a way to add another singleton dynamically later on? I've not found a way to do it from the API docs.
I have not tried this myself, but I found a blog post where this is described: http://sarbarian.wordpress.com/2010/03/07/resteasy-and-osgi-perfect-match/
During deployment, RESTEasy puts it's registry in the servlet context. The idea suggstested in the blog, is that you fetch the registry from the servlet context, and then add your resource class.
Something like this:
import org.jboss.resteasy.spi.Registry;
Object resource = new MyService();
Registry registry = (Registry) context.getAttribute(Registry.class.getName());
registry.addSingletonResource(resource);
I have tried this myself, and although it was nerve-wracking, it works great. We've got an infrastructure where several independent projects (plug-ins) are imported and loaded by our main application, and we wanted to include access to them in our existing RestEasy API (and Swagger documentation).
We originally hard-coded the class-loading into our main Rest Application class, which required all of the plug-ins to be displayed at all times in our API. To avoid that and to re-instate the independence of those projects (all, some, or none may be included at any given time), we created dynamic methods that return the feature/target class itself, which is loaded during the bootstrap phase of the RestEasy framework. It worked like a charm.
Within our Rest Application class, we implemented it as follows:
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(mainAPIStuff.class);
classes.add(plugin1.class);
classes.add(plugin2.class);
classes.add(plugin3.class);
.
.
.
return classes;
}
That was the old way. The new way was to loop through all of our plugins and return a hashSet of the classes that the plugins provide:
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
classes.add(mainAPIStuff.class);
classes.addAll(pluginsHelper.getClasses());
return classes;
}
The pluginsHelper has sundry shared plugin methods and administrative tools, like getClasses(), which does basically this:
public static Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<>();
// Probe plugins for their Rest Class implementation
List plugins = getCurrentlyInstalledPluginsFromOurSystem();
for (PluginObject plugin : plugins) {
Class<?> clazz = plugin.getPluginRestClass();
if (clazz != null) {
classes.add(clazz);
}
}
return classes;
}
RestEasy builds the Rest targets dynamically when any target is called, so all of the plugin installation, startup, config has already completed and the system is in the correct state before it is called. This is very valuable to understand, since then you can do all of the RestEasy class manipulation and loading at call time.
I use Reateasy with Undertow in embedded environment, where I manually instantiate ResteasyDeployment
, and register Resource class is really easy, see code snippet blow:
UndertowJaxrsServer undertowJaxrsServer = new UndertowJaxrsServer();
ResteasyDeployment resteasyDeployment = new ResteasyDeployment();
undertowJaxrsServer.start();
resteasyDeployment.start();
final DeploymentInfo undertowDeployment =
undertowJaxrsServer
.undertowDeployment(resteasyDeployment)
.setContextPath("/abc")
.setDeploymentName("TEST")
.setClassLoader(Thread.currentThread().getContextClassLoader());
undertowJaxrsServer.deploy(undertowDeployment);
resteasyDeployment.getRegistry().addSingletonResource(new ResourceApiImpl());
精彩评论