1 package de.spring.webservices.rest.wadl;
3 import java.lang.annotation.Annotation;
4 import java.lang.reflect.Method;
8 import javax.servlet.http.HttpServletRequest;
9 import javax.xml.namespace.QName;
11 import org.apache.commons.lang.StringUtils;
12 import org.jvnet.ws.wadl.Application;
13 import org.jvnet.ws.wadl.Doc;
14 import org.jvnet.ws.wadl.Param;
15 import org.jvnet.ws.wadl.ParamStyle;
16 import org.jvnet.ws.wadl.Representation;
17 import org.jvnet.ws.wadl.Request;
18 import org.jvnet.ws.wadl.Resource;
19 import org.jvnet.ws.wadl.Resources;
20 import org.jvnet.ws.wadl.Response;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.context.ApplicationContext;
23 import org.springframework.http.HttpStatus;
24 import org.springframework.http.MediaType;
25 import org.springframework.stereotype.Controller;
26 import org.springframework.web.bind.annotation.PathVariable;
27 import org.springframework.web.bind.annotation.RequestMapping;
28 import org.springframework.web.bind.annotation.RequestMethod;
29 import org.springframework.web.bind.annotation.RequestParam;
30 import org.springframework.web.bind.annotation.ResponseBody;
31 import org.springframework.web.bind.annotation.ResponseStatus;
32 import org.springframework.web.bind.annotation.RestController;
33 import org.springframework.web.bind.annotation.ValueConstants;
34 import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
35 import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
38 * Taken from: http://javattitude.com/2014/05/26/wadl-generator-for-spring-rest/
40 * With some modifications.
44 @RequestMapping("/rest.wadl")
45 public class WADLController {
46 private static final String NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema" ;
47 private static final String WADL_TITLE = "Spring REST Service WADL";
49 private final AbstractHandlerMethodMapping<RequestMappingInfo> handlerMapping;
50 private final ApplicationContext context;
53 public WADLController(AbstractHandlerMethodMapping<RequestMappingInfo> handlerMapping, ApplicationContext context) {
54 this.handlerMapping = handlerMapping;
55 this.context = context;
58 @RequestMapping(produces = { MediaType.APPLICATION_XML_VALUE }, method=RequestMethod.GET )
59 public @ResponseBody Application generateWadl(HttpServletRequest request) {
60 Application result = new Application();
63 doc.setTitle(WADL_TITLE);
64 result.getDoc().add(doc);
66 Resources wadlResources = new Resources();
67 wadlResources.setBase(getBaseUrl(request));
69 handlerMapping.getHandlerMethods().forEach( (mappingInfo, handlerMethod) -> {
70 Object object = handlerMethod.getBean();
71 Object bean = context.getBean(object.toString());
72 if(!bean.getClass().isAnnotationPresent(RestController.class)) {
76 mappingInfo.getMethodsCondition().getMethods().forEach(httpMethod -> {
77 Resource wadlResource = null;
78 org.jvnet.ws.wadl.Method wadlMethod = new org.jvnet.ws.wadl.Method();
80 Set<String> pattern = mappingInfo.getPatternsCondition().getPatterns();
81 for (String uri : pattern) {
82 wadlResource = createOrFind(uri, wadlResources);
83 wadlResource.setPath(uri);
86 wadlMethod.setName(httpMethod.name());
87 Method javaMethod = handlerMethod.getMethod();
88 wadlMethod.setId(javaMethod.getName());
89 Doc wadlDocMethod = new Doc();
90 wadlDocMethod.setTitle(javaMethod.getDeclaringClass().getSimpleName() + "." + javaMethod.getName());
91 wadlMethod.getDoc().add(wadlDocMethod);
94 Request wadlRequest = new Request();
95 Annotation[][] annotations = javaMethod.getParameterAnnotations();
96 Class<?>[] paramTypes = javaMethod.getParameterTypes();
98 for (Annotation[] annotation : annotations) {
99 Class<?> paramType =paramTypes[i];
101 for (Annotation annotation2 : annotation) {
103 Param wadlParam = doParam(annotation2, paramType);
104 if (wadlParam != null) {
105 wadlRequest.getParam().add(wadlParam);
109 if (!wadlRequest.getParam().isEmpty() ) {
110 wadlMethod.setRequest(wadlRequest);
114 Set<MediaType> mediaTypes = mappingInfo.getProducesCondition().getProducibleMediaTypes();
115 if (!mediaTypes.isEmpty()) {
116 ResponseStatus status = handlerMethod.getMethodAnnotation(ResponseStatus.class);
117 Response wadlResponse = doResponse(mediaTypes, status);
118 wadlMethod.getResponse().add(wadlResponse);
122 wadlResource.getMethodOrResource().add(wadlMethod);
126 result.getResources().add(wadlResources);
131 private Param doParam(Annotation annotation2, Class<?> paramType) {
132 Param wadlParam = null;
134 if (annotation2 instanceof RequestParam ) {
135 RequestParam param = (RequestParam)annotation2;
137 wadlParam = new Param();
138 QName nm = convertJavaToXMLType(paramType);
139 if (StringUtils.isNotEmpty(nm.getLocalPart())) {
140 wadlParam.setType(nm);
142 wadlParam.setName(param.value());
145 if (!ValueConstants.DEFAULT_NONE.equals(param.defaultValue())) {
146 String defaultValue = cleanDefault(param.defaultValue());
147 if (StringUtils.isNotEmpty(defaultValue) ) {
148 wadlParam.setDefault(defaultValue);
152 wadlParam.setStyle(ParamStyle.QUERY);
153 wadlParam.setRequired(param.required());
154 } else if (annotation2 instanceof PathVariable ) {
155 PathVariable param = (PathVariable)annotation2;
157 wadlParam = new Param();
158 QName nm = convertJavaToXMLType(paramType);
159 if (StringUtils.isNotEmpty(nm.getLocalPart())) {
160 wadlParam.setType(nm);
162 wadlParam.setName(param.value());
165 wadlParam.setStyle(ParamStyle.TEMPLATE);
166 wadlParam.setRequired(true);
172 private Response doResponse(Set<MediaType> mediaTypes, ResponseStatus status) {
173 Response wadlResponse = new Response();
175 mediaTypes.forEach(mediaType -> {
176 Representation wadlRepresentation = new Representation();
177 wadlRepresentation.setMediaType(mediaType.toString());
178 wadlResponse.getRepresentation().add(wadlRepresentation);
181 wadlResponse.getStatus().add(getResposeValue(status));
186 private long getResposeValue(ResponseStatus status) {
188 return HttpStatus.OK.value();
190 HttpStatus httpcode = status.value();
191 return httpcode.value();
195 private QName convertJavaToXMLType(Class<?> type) {
196 QName nm = new QName("");
197 String classname = type.toString();
198 classname = classname.toLowerCase();
200 if (classname.indexOf("string") >= 0) {
201 nm = new QName(NAMESPACE_URI, "string", "xs");
202 } else if (classname.indexOf("integer") >= 0) {
203 nm = new QName(NAMESPACE_URI, "int", "xs");
204 } else if (classname.indexOf("long") >= 0) {
205 nm = new QName(NAMESPACE_URI, "long", "xs");
211 private Resource createOrFind(String uri, Resources wadResources) {
212 List<Resource> current = wadResources.getResource();
213 for(Resource resource:current) {
214 if(resource.getPath().equalsIgnoreCase(uri)){
218 Resource wadlResource = new Resource();
219 current.add(wadlResource);
223 private String getBaseUrl(HttpServletRequest request) {
224 String requestUri = request.getRequestURI();
225 int index = requestUri.lastIndexOf('/');
226 requestUri = requestUri.substring(0, index);
228 return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + requestUri;
231 private String cleanDefault(String value) {
232 value = value.replaceAll("\t", "");
233 value = value.replaceAll("\n", "");