example chrome jboss resteasy

jboss - chrome - ¿Listar todos los puntos finales expuestos/disponibles del servicio RestEasy?



resteasy example (5)

EDITAR:

Vea este gist para un ejemplo "más limpio": https://gist.github.com/wonderb0lt/10731371

Si es posible. Quizás te gustaría saber cómo? :)

Aquí hay un ejemplo de "quick-n-dirty":

import org.jboss.resteasy.annotations.providers.jaxb.Formatted; import org.jboss.resteasy.annotations.providers.jaxb.Wrapped; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.core.ResourceInvoker; import org.jboss.resteasy.core.ResourceMethod; import org.jboss.resteasy.core.ResourceMethodRegistry; import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.junit.Test; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlValue; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class PrintAllResourcesTest { @Test public void name_StateUnderTest_ExpectedBehavior() throws Exception { Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); dispatcher.getRegistry().addSingletonResource(new MetaService()); dispatcher.getRegistry().addSingletonResource(new Service()); MockHttpResponse response = new MockHttpResponse(); MockHttpRequest request = MockHttpRequest.get("/meta") .accept(MediaType.APPLICATION_XML); dispatcher.invoke(request, response); /*<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <resources> <resource method="GET">/service/</resource> <resource method="POST">/service/</resource> </resources>*/ String result = response.getContentAsString(); } @XmlRootElement(name = "resource") public static final class JaxRsResource { @XmlAttribute String method; @XmlValue String uri; public JaxRsResource() {} public JaxRsResource(String method, String uri) { this.method = method; this.uri = uri; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; JaxRsResource that = (JaxRsResource) o; if (method != null ? !method.equals(that.method) : that.method != null) return false; if (uri != null ? !uri.equals(that.uri) : that.uri != null) return false; return true; } @Override public int hashCode() { int result = method != null ? method.hashCode() : 0; result = 31 * result + (uri != null ? uri.hashCode() : 0); return result; } } @Path("/service") public static final class Service { @GET @Path("/") public String getStuff(){ return ""; } @POST @Path("/") public String postStuff(){ return ""; } } @Path("/meta") public static final class MetaService { @Context Dispatcher dispatcher; @GET @Path("/") @Wrapped(element = "resources") @Formatted public Set<JaxRsResource> getAllResources(){ Set<JaxRsResource> resources = new HashSet<JaxRsResource>(); ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry(); for (Map.Entry<String, List<ResourceInvoker>> entry : registry.getRoot().getBounded().entrySet()) { for (ResourceInvoker invoker : entry.getValue()) { ResourceMethod method = (ResourceMethod) invoker; if(method.getMethod().getDeclaringClass() == getClass()){ continue; } for (String verb : method.getHttpMethods()) { String uri = entry.getKey(); resources.add(new JaxRsResource(verb, uri)); } } } return resources; } } }

¿Es posible enumerar todos los puntos finales expuestos / disponibles del servicio RestEasy de una manera sencilla?


En caso de que alguien siga buscando "/ resteasy / registry" en tu aplicación y

proporciona salida XML de todos los puntos finales registrados, clases / métodos asociados, etc.

FYI resteasy-jaxb-provider proporciona esta funcionalidad


Hay un complemento RestEasy, "stats", que expone .../resteasy/registry .

Necesita estar registrado en web.xml :

<context-param> <param-name>resteasy.resources</param-name> <param-value>org.jboss.resteasy.plugins.stats.RegistryStatsResource</param-value> </context-param>

Ejemplo de respuesta:

<registry> <resource uriTemplate="/resource"> <delete class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="delete" invocations="0"/> <head class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="head" invocations="0"/> </resource> <resource uriTemplate="/locator"> <locator class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="getLocator"/> </resource> <resource uriTemplate="/resteasy/registry"> <get class="org.jboss.resteasy.plugins.stats.RegistryStatsResource" method="get" invocations="2"> <produces>application/xml</produces> <produces>application/json</produces> </get> </resource> <resource uriTemplate="/entry/{foo:.*}"> <post class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="post" invocations="0"> <produces>text/xml</produces> <consumes>application/json</consumes> </post> <put class="org.jboss.resteasy.test.providers.jaxb.resource.StatsResource" method="put" invocations="0"> <produces>text/xml</produces> <consumes>application/json</consumes> </put> </resource> </registry>

Dependencia de Maven:

<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>3.0.8.Final</version> </dependency>

Ver por ejemplo EAP docs y este EAP 7 Jira


Incluso es un post antiguo, doy mi respuesta aquí.

Aquí está la implementación de RestEasy enviada con JBoss. Puedes usarlo, o puedes escribir el tuyo. La implementación devuelve un objeto con una propiedad de matriz donde puede encontrar una cadena uriTemplate para cada recurso RestEasy.

Debe recorrer todas las entradas y obtener la información que necesita:

RegistryData.entries.get (index) .uriTemplate

La implementación del método org.jboss.resteasy.plugins.stats.RegistryStatsResource.get:

public RegistryData get() throws JAXBException { ResourceMethodRegistry registry = (ResourceMethodRegistry)ResteasyProviderFactory.getContextData(Registry.class); RegistryData data = new RegistryData(); Iterator i$ = registry.getRoot().getBounded().keySet().iterator(); label85: while(i$.hasNext()) { String key = (String)i$.next(); List<ResourceInvoker> invokers = (List)registry.getRoot().getBounded().get(key); RegistryEntry entry = new RegistryEntry(); data.getEntries().add(entry); entry.setUriTemplate(key); Iterator i$ = invokers.iterator(); while(true) { while(true) { if (!i$.hasNext()) { continue label85; } ResourceInvoker invoker = (ResourceInvoker)i$.next(); if (invoker instanceof ResourceMethod) { ResourceMethod rm = (ResourceMethod)invoker; Object method; for(Iterator i$ = rm.getHttpMethods().iterator(); i$.hasNext(); entry.getMethods().add(method)) { String httpMethod = (String)i$.next(); method = null; if (httpMethod.equals("GET")) { method = new GetResourceMethod(); } else if (httpMethod.equals("PUT")) { method = new PutResourceMethod(); } else if (httpMethod.equals("DELETE")) { method = new DeleteResourceMethod(); } else if (httpMethod.equals("POST")) { method = new PostResourceMethod(); } else if (httpMethod.equals("OPTIONS")) { method = new OptionsResourceMethod(); } else if (httpMethod.equals("TRACE")) { method = new TraceResourceMethod(); } else if (httpMethod.equals("HEAD")) { method = new HeadResourceMethod(); } ((ResourceMethodEntry)method).setClazz(rm.getResourceClass().getName()); ((ResourceMethodEntry)method).setMethod(rm.getMethod().getName()); AtomicLong stat = (AtomicLong)rm.getStats().get(httpMethod); if (stat != null) { ((ResourceMethodEntry)method).setInvocations(stat.longValue()); } else { ((ResourceMethodEntry)method).setInvocations(0L); } MediaType[] arr$; int len$; int i$; MediaType mediaType; if (rm.getProduces() != null) { arr$ = rm.getProduces(); len$ = arr$.length; for(i$ = 0; i$ < len$; ++i$) { mediaType = arr$[i$]; ((ResourceMethodEntry)method).getProduces().add(mediaType.toString()); } } if (rm.getConsumes() != null) { arr$ = rm.getConsumes(); len$ = arr$.length; for(i$ = 0; i$ < len$; ++i$) { mediaType = arr$[i$]; ((ResourceMethodEntry)method).getConsumes().add(mediaType.toString()); } } } } else { ResourceLocator rl = (ResourceLocator)invoker; SubresourceLocator locator = new SubresourceLocator(); locator.setClazz(rl.getMethod().getDeclaringClass().getName()); locator.setMethod(rl.getMethod().getName()); entry.setLocator(locator); } } } } return data; }

Vea también: Administración de WildFly - listar / detectar puntos finales REST implementados en WildFly


Tuve que ajustar el ejemplo de "limpiador" que era excelente para empezar. Estoy usando RestEasy 3.07 y también quería tener el valor de anotación de ruta de cada método. Espero que esta modificación pueda ser de ayuda para otros.

import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.Set; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.core.ResourceInvoker; import org.jboss.resteasy.core.ResourceMethodInvoker; import org.jboss.resteasy.core.ResourceMethodRegistry; import org.springframework.stereotype.Component; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @Component @Path("/overview") public class OverviewResource { private static final class MethodDescription { private String method; private String fullPath; private String produces; private String consumes; public MethodDescription(String method, String fullPath, String produces, String consumes) { super(); this.method = method; this.fullPath = fullPath; this.produces = produces; this.consumes = consumes; } } private static final class ResourceDescription { private String basePath; private List<MethodDescription> calls; public ResourceDescription(String basePath) { this.basePath = basePath; this.calls = Lists.newArrayList(); } public void addMethod(String path, ResourceMethodInvoker method) { String produces = mostPreferredOrNull(method.getProduces()); String consumes = mostPreferredOrNull(method.getConsumes()); for (String verb : method.getHttpMethods()) { calls.add(new MethodDescription(verb, path, produces, consumes)); } } private static String mostPreferredOrNull(MediaType[] mediaTypes) { if (mediaTypes == null || mediaTypes.length < 1) { return null; } else { return mediaTypes[0].toString(); } } public static List<ResourceDescription> fromBoundResourceInvokers( Set<Map.Entry<String, List<ResourceInvoker>>> bound) { Map<String, ResourceDescription> descriptions = Maps.newHashMap(); for (Map.Entry<String, List<ResourceInvoker>> entry : bound) { Method aMethod = ((ResourceMethodInvoker) entry.getValue().get(0)).getMethod(); String basePath = aMethod.getDeclaringClass().getAnnotation(Path.class).value(); if (!descriptions.containsKey(basePath)) { descriptions.put(basePath, new ResourceDescription(basePath)); } for (ResourceInvoker invoker : entry.getValue()) { ResourceMethodInvoker method = (ResourceMethodInvoker) invoker; String subPath = null; for(Annotation annotation : method.getMethodAnnotations()) { if(annotation.annotationType().equals(Path.class)) { subPath = ((Path) annotation).value(); break; } } descriptions.get(basePath).addMethod(basePath + subPath, method); } } return Lists.newLinkedList(descriptions.values()); } } @GET @Path("/") @Produces(MediaType.APPLICATION_JSON) public List<ResourceDescription> getAvailableEndpoints(@Context Dispatcher dispatcher) { ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry(); return ResourceDescription.fromBoundResourceInvokers(registry.getBounded().entrySet()); } @GET @Path("/") @Produces(MediaType.TEXT_HTML) public Response getAvailableEndpointsHtml(@Context Dispatcher dispatcher) { StringBuilder sb = new StringBuilder(); ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry(); List<ResourceDescription> descriptions = ResourceDescription.fromBoundResourceInvokers(registry.getBounded() .entrySet()); sb.append("<h1>").append("REST interface overview").append("</h1>"); for (ResourceDescription resource : descriptions) { sb.append("<h2>").append(resource.basePath).append("</h2>"); sb.append("<ul>"); for (MethodDescription method : resource.calls) { sb.append("<li> ").append(method.method).append(" "); sb.append("<strong>").append(method.fullPath).append("</strong>"); sb.append("<ul>"); if (method.consumes != null) { sb.append("<li>").append("Consumes: ").append(method.consumes).append("</li>"); } if (method.produces != null) { sb.append("<li>").append("Produces: ").append(method.produces).append("</li>"); } sb.append("</ul>"); } sb.append("</ul>"); } return Response.ok(sb.toString()).build(); } }

(En otra nota, quizás haya algo disponible, o puedo comenzar a trabajar, para modelar la lista de recursos y la descripción que ServiceStack hace muy bien: http://mono.servicestack.net/Content/Images/MetadataIndex.png )