Im using enunciate to document my REST API. Im able to generate docs properly and have been using it for quite some time.
My issue now is.. Ive few Service classes with multiple endpoint methods.
public interface UserLoginService {
//This method should be DOcumented
#Path("/login")
#POST
#Consumes({"application/xml", "application/json"})
#Produces({"application/xml", "application/json"})
#Transactional(
readOnly=false,
rollbackForClassName="MyExceptionClass",
propagation=Propagation.REQUIRED
)
#Deprecated
public UserDetails performLogin(LoginObj loginobj);
//This method should be skipped
#Path("/logout")
#GET
#Consumes({"application/xml", "application/json"})
#Produces({"application/xml", "application/json"})
#Transactional(
readOnly=false,
rollbackForClassName="MyException",
propagation=Propagation.REQUIRED
)
public UserDetails logout(#QueryParam("userid") String userid);
}
In those service methods some are public and some are used internally. I wanted to generated doc for only those Rest methods which are supposed to be public. I searched in enunciate couldnt find anyway to skip few methods , though im using exclude api classes to exclude classes.
Is there any way this can be achieved. I dont want to create separate classes only bcoz of documentation. If enunciate dosent do this any other doc tools which can be easily adapted from existing enunciate javadoc written.
FYI, version 1.27 will include the notion of Enunciate Facets that are more flexible in excluding facets of your API.
I was using the old version of enunciate. The latest version has an annotation #ExcludeFromDocumentation. Though I saw this annotation It was written in doc that this is applicable for only Jaxb objs. I saw in their jira a defect raised and fixed for my issue. This annotation now can be used for classes/methods . If used against a REST method then the method will not be documented.
Related
I am currently integrating Swagger (swagger-jaxrs artifact in version 1.5.7) into our existing JAX-RS REST application. After adding Swagger I added the #Api annotation to our interface class and already got a documentation which doesn't look to bad.
Unfortunately Swagger does not honor the #Produces annotations on my API methods until I annotate those methods with #ApiOperation:
Doesn't list text/plain as the returned media type:
#GET
#Path("/overallStatus")
#Produces(MediaType.TEXT_PLAIN)
public String getOverallStatus() {
}
Does list it:
#GET
#Path("/overallStatus")
#Produces(MediaType.TEXT_PLAIN)
#ApiOperation(value = "Get the overall system status")
public String getOverallStatus() {
}
Is there a way to have the media type in the Swagger output without adding #ApiOperation to all of them? Since the required information is already there, I don't see why I would need it.
You have to add the #ApiOperation to your JAX-RS endpoints since methods without the #ApiOperation annotation will be ignored as per the Swagger Wiki page:
Only methods that are annotated with #ApiOperation will be scanned and added the Swagger definition.
You can find more information here: https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X#apioperation
I am trying to use PATCH method in my client using CXF implementation of JAX-RS.
At first I defined the PATCH annotation as
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#HttpMethod("PATCH")
public #interface PATCH {
}
Referencing what was written here :
How to have a #PATCH annotation for JAX-RS?
Then I found out #PATCH was added into CXF 3.1.2, so I changed version in my maven's pom.xml and indeed there is public #interface PATCH inside of package org.apache.cxf.jaxrs.ext; and the code actually looks exactly as what I posted above.
However, when I try to use this annotation on my service definition as
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public interface AbcService {
#PATCH
#Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
I end up with the java.net.ProtocolException: Invalid HTTP method: PATCH as was said in the queston link I posted above. They discuss some solution for this with Jersey, however what I can I do in CXF, so that I can use :
AbcService abcService = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
abcService.patchSomething(new RequestObject('something'));
So I have couple of questions:
How can I make this work ? No I need to write custom CXF interceptor ?
Why did they add the PATCH annotation into CXF if it doesn't work ?
Some guys in the other topic said that the mentioned PATCH annotation definition works for them. How come ? Does it only make trouble on the client side, and if so why is it ?
Why I can't find this annotation in CXF documentation ? I looked into org.apache.cxf.jaxrs.ext package at http://cxf.apache.org/javadoc/latest/ and I don't see any PATCH. Yet in the latest cxf 3.1.2 I really can find it in this package.
It turns out it's cause because in JAVA7, HttpURLConnection doesn't support PATCH, the supported methods in that class are defined statically as
private static final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
};
However it is possible to send PATCH request in CXF, but the Conduit object must be of type AsyncHTTPConduit.
To make CXF use AsyncHTTPConduit, you can programatically achieve it like this
AbcService service = JAXRSClientFactory.create(myURI, AbcService.class, myProviders, true);
WebClient.getConfig(service).getRequestContext().put("use.async.http.conduit", true);
service.patchEnvironmentParameters(patchRequest);
Or
WebClient client = WebClient.create("http://localhost:53261/v1-0/api/environment/parameters");
WebClient.getConfig(client).getRequestContext().put("use.async.http.conduit", true);
client.invoke("PATCH", "{}");
But beware !! In order to make this work, you have put this dependency into your project
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-hc</artifactId>
<version>${cxf.version}</version>
</dependency>
Also make sure that you use the same version of cxf-rt-transports-http-hc and cxf.
But as you can see what I described doesn't solve the original issue, this way I just made 1 specific PATCH request. However in my project there are many PATCH services defined using interfaces like I showed originally
public interface AbcService {
#PATCH
#Path("/abc/efg")
public SomeDTO patchSomething(RequestObject request);
}
So in order to use the AsyncHTTPConduit only on PATCH methods, I had to write custom CXF interceptor, about which you can learn more here http://cxf.apache.org/docs/interceptors.html
The interceptor I wrote runs in PRE_LOGIC phase and it checks what kind of method is used and in case it PATCH, it defined the conduit property. Then in latter phases of service invocation, CXF uses this property to choose which Conduit implementation should be used, and so after
if ( message.get(Message.HTTP_REQUEST_METHOD).equals("PATCH") {
message.put("use.async.http.conduit", true);
}
the AsyncHTTPConduit instance will be used with which the PATCH will work.
Could you try to replace the use of #PATCH with #POST in your code to see if it works ? Your AbcService interface misses an #Path annotation at the type level (unless it is a subresource ?), so it might be worth trying with a standard HTTP verb first to make sure everything else is properly configured.
Some time ago in one of the projects I found #WebService annotations on some of the jersey root(#Path) resource classes. As far as I understood at the time it was some legacy code or simply a misused JAX-WS annotation. Recently I stumbled upon this post in which mixing JAX-RS service with #WebService annotation for the sake of EJB mentioned(as a side note, that project I worked on didn't make use of EJB at all, so I still think it was an improper use of #WebService). As a result of all that I am now confused if it is in general justifiable to mix #WebService and JAX-RS. What are the cases for that? Anything apart from EJB features mentioned?
Exposing a JAX-RS bean as the methods of a SOAP WS using #WebService may be technically possible. It will not lead to a good API design.
Consider some very common JAX-RS methods:
#GET
#Path("/foos")
#Produces("application/json")
public Response getFoos() {
// get all Foos
List<Foo> foos = ...;
return Response.ok(foos).build();
}
#GET
#Path("/foos/{id}")
#Produces("application/json")
public Response getSingleFoo(#PathParam("id") String id) {
// get the Foo
Foo foo = ...;
return Response.ok(foo).build();
}
It is immediatley obvious how the URLs to call these methods will be structured and what the result will be.
But exposing these methods using #WebService leads to many questions:
What is a Response in a SOAP response?
Will the response use JSON as the representation?
How are the methods called?
I can imagine no usecase that is not completely trivial for which it makes sense to expose the same method using both JAX-RS and JAX-WS. It can either be a useful method for one but not for both.
Don't do this.
I tried to generate a json response earlier using spring-mvc (annotation) . After so may failure i find out some check point :
I need to add <mvc:annotation-driven/> in my servelet mapper. although i don't know the reason.
Then I need to add #ResponseBody annotation which should bound the return value as http response as the documentation says.
And I also need add some jacson dependency.
Did i missed something?
Now i have bunch of questions
why we have to add that in my servelet xml and how this whole process is working?
As json response is most commonly used when why spring need jackson dependency to generate json?
some days ago i was doing Struts2 generating json response there was much simple.
Is there any way to do it more easily in spring-mvc .?
At first you should understand that <mvc:annotation-driven/> annotation used for many cases not only for generating json response in Spring. This annotation allow to use different annotations in Spring mvc classes like:#NumberFormat #DateFormat #Controller #Valid and of course #ResponseBody.
To generate json response you just need #ResponseBody annotation in your controller or servlet and import libraries for processing JSON.
Recently java has oun set of APIs for processing JSON as part of Java EE 7 JSR 353 actually it has clean Oracle tutorial. Also you can use third party libraries like Jackson. To process (parse, generate, transform, and query) JSON text it's necessarily to have one of this libs.
You can learn about most popular third party libraries and their performance in this article
Here you can see simple example.
If you are using jacson you can do something like:
Your Model
public class Shop {
String name;
String staffName[];
}
Your Controller
#Controller
#RequestMapping("/shop/list")
public class JSONController {
#RequestMapping(value="{name}", method = RequestMethod.GET)
public #ResponseBody Shop getShopInJSON(#PathVariable String name) {
Shop shop = new Shop();
shop.setName(name);
shop.setStaffName(new String[]{"mkyong1", "mkyong2"});
return shop;
}
}
mvc-dispatcher-servlet.xml
<context:component-scan base-package="com.example.mypackage" />
<mvc:annotation-driven />
Basically, you need check if:
Your Jackson library is existed in the project classpath
The mvc:annotation-driven is enabled
Return method annotated with #ResponseBody
I have a REST api written with JAX-RS, and I need to add authentication to it. So far all the information I've been able to find about it has suggestions for doing it via spring, which I'm not using. Is there something already existing, or would it be easy to write, something that will let me annotate either a method, or the entire class which would force auth headers to be present?
I'm using tomcat6 and jersey, if that matters.
Something like:
#Path("api")
public class Api {
#GET
#AuthenticationRequired
public Response getInfo(...) {...}
}
I think you want import javax.annotation.Security.RolesAllowed;
The annotation itself looks like this
#Path("/helloworld")
#RolesAllowed({"ADMIN", "ORG1"})
public class helloWorld {
#GET
#Path("sayHello")
#Produces("text/plain")
#RolesAllowed("ADMIN")
public String sayHello() {
return "Hello World!";
}
}
I would manage security at the container level. Here's a good writeup if you happen to be using Apache CXF:
http://cxf.apache.org/docs/secure-jax-rs-services.html
And here's an example for Glassfish:
http://www.butonic.de/2010/06/18/a-simple-jax-rs-security-context-example-in-glassfish/
Here's one more link, which discusses JSR 250 annotations (e.g. #RolesAllowed):
http://www-01.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.doc/ae/twbs_jaxrs_impl_securejaxrs_annotations.html