More and more applications are composed of REST services. In JavaEE land it means you develop and expose JAX-RS services.
Once developped and well tested with TomEE the first thing you will realize is that to make an API useful you need to document it. There are a lot of ways to do it but Swagger seems to be the trendy one and it is indeed a nice solution as we’ll see in this post.
For the purpose of this article we’ll start from this simple service:
@Transactional @ApplicationScoped @Path("users") @Produces(MediaType.APPLICATION_JSON) public class UserResource { @GET public UserPage getUsers(@QueryParam("number") final int number, @QueryParam("offset") final int offset) { // ... } @GET @Path("{id}") public UserModel get(@PathParam("id") final long userId) { // ... } }
This is a fully JavaEE (7 in this case) service returning user(s). To “expose” it with swagger we need to decorate it with @Api
and we can document a bit more each method and parameters with a set of dedicated annotations like @ApiOperatoin
or @ApiParam
::
@Transactional @ApplicationScoped @Path("users") @Produces(MediaType.APPLICATION_JSON) @Api("user") // swagger tag public class UserResource { @GET @ApiOperation(value = "Find users.") //swagger method description/comment public UserPage getUsers(@QueryParam("number") @ApiParam(value = "page size", defaultValue = "20") // swagger param doc @DefaultValue("20") final int number, @QueryParam("offset") @ApiParam(value = "item offset", defaultValue = "0") @DefaultValue("0") final int offset) { // ... } @GET @Path("{id}") @ApiOperation(value = "Find a user by id.") public UserModel get(@PathParam("id") @ApiParam(value = "user id", required = true) final long userId) { // ... } }
Sure it adds several annotations but then swagger will be able to generate either at build time with jaxrs-analyzer or at runtime like we’ll see the corresponding model.
Tip: of course you can also just write your model in YAML or JSON manually before having developped the service and just expose it with the same technique we’ll see now.
Once the model is computed swagger is able to expose it as JSON or YAML. Until here it is cool for machine to machine API validation but not very useful for API documentation which is intended for users first.
For that purpose you need to use another part of swagger which is swagger-ui which just reads the previous model and creates a GUI from it.
Let’s see how to set it up in a EE server – TomEE for us.
Dependencies
You only need swagger-jaxrs and swagger-ui to set it up:
<dependency> <groupId>io.swagger</groupId> <artifactId>swagger-jaxrs</artifactId> <version>1.5.3</version> <exclusions> <!-- API are useless since in javaee-api --> <exclusion> <groupId>javax.ws.rs</groupId> <artifactId>jsr311-api</artifactId> </exclusion> <exclusion> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> </exclusion> <!-- not useful for the GUI -> only json for us --> <exclusion> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </exclusion> <exclusion> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-joda</artifactId> </exclusion> <!-- we don't use reflections so no need of javassist --> <exclusion> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> </exclusion> <exclusion> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> </exclusion> <!-- we'll reuse the container one or add an impl as well to your app --> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>swagger-ui</artifactId> <version>2.1.8-M1</version> </dependency>
Swagger-ui is a webjars containing the UI and you can of course use any other frontend solution to get the javascript/css but webjars are a fast solution which fits very well a blog post :).
Swagger-jaxrs is the module bringing the stack needed to introspect the swagger annotations and create the model the UI needs. As you can see you can exclude a bunch of transitive dependencies we’ll not use and which can conflict with your application or container – or even just leak.
API metadata
We already saw you can add metadata (annotations) on your services but you can also add a title, version, … to your API and you need to add a base path (JAX-RS mapping) to let swagger be able to create correct URLs for your endpoints (keep in mind if you are exposed behind a proxy swagger can sometimes not guess the external endpoint).
To do so the easiest solution is to add the swagger servlet in your web.xml and set it up as init parameters:
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <servlet> <servlet-name>swagger</servlet-name> <servlet-class>io.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class> <init-param> <param-name>api.version</param-name> <param-value>${project.version}</param-value> </init-param> <init-param> <param-name>swagger.api.basepath</param-name> <param-value>http://localhost:8080/app/api</param-value> </init-param> <init-param> <param-name>swagger.api.title</param-name> <param-value>My Awesome API</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> </web-app>
Notes:
- swagger basepath can be a full URL or partial one.
- here we used maven version for the API version and added the web.xml to be filtered thanks to the maven war plugin configuration. In practise the API version rarely follows the project version but it was mainly to remind you the build tool can still be central and used even if the configuration is in web.xml file.
Note: no need of any servlet mapping, servlet API is just used to initialized swagger internals – there are alternatives but they need code compared to this one.
JAX-RS integration
Once swagger-jaxrs is added to your project you can use the provided swagger ApiListingResource JAX-RS resource to expose the swagger model at /swagger URL. If your container and JAXRS application is configured to use scanning nothing needed to get it otherwise keep in mind to add it to the resources you expose.
Now adding swagger dependencies also adds jackson and its jaxrs providers. This means you can get conflicts if it is not the one you want. To avoid that – and for TomEE case – we’ll add a WEB-INF/openejb-jar.xml specifying we want to use Apache Johnzon as JAX-RS JSON provider:
<?xml version="1.0" encoding="UTF-8"?> <openejb-jar> <pojo-deployment class-name="jaxrs-application"> <properties> # swagger brings back jackson*, maybe not what you want in your app so let's take the control over providers cxf.jaxrs.skip-provider-scanning = true # let's keep the default TomEE JSON provider (johnzon) cxf.jaxrs.providers = org.apache.johnzon.jaxrs.JohnzonProvider </properties> </pojo-deployment> </openejb-jar>
Of course we could use jackson but if your application already uses johnzon specific features this allows to keep it and it doesn’t break swagger :).
Note: using JAX-RS integration supposes you use an Application subclass. if not you need to set up swagger to scan for resources or use CXF (Swagger2Feature) / Jersey / Spring integration.
Set it up the Swagger GUI
Finally to setup the swagger GUI we just need to add an index.jsp (or any other location if swagger will not be your home page) containing:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <title>Java WordPress API</title> <link href='webjars/swagger-ui/2.1.8-M1/css/typography.css' media='screen' rel='stylesheet' type='text/css'/> <link href='webjars/swagger-ui/2.1.8-M1/css/reset.css' media='screen' rel='stylesheet' type='text/css'/> <link href='webjars/swagger-ui/2.1.8-M1/css/screen.css' media='screen' rel='stylesheet' type='text/css'/> <link href='webjars/swagger-ui/2.1.8-M1/css/reset.css' media='print' rel='stylesheet' type='text/css'/> <link href='webjars/swagger-ui/2.1.8-M1/css/screen.css' media='print' rel='stylesheet' type='text/css'/> <script src="webjars/swagger-ui/2.1.8-M1/lib/shred.bundle.js" type="text/javascript"></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/jquery-1.8.0.min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/jquery.slideto.min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/jquery.wiggle.min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/jquery.ba-bbq.min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/handlebars-2.0.0.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/underscore-min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/backbone-min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/swagger-client.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/swagger-ui.min.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/highlight.7.3.pack.js' type='text/javascript'></script> <script src='webjars/swagger-ui/2.1.8-M1/lib/marked.js' type='text/javascript'></script> </head> <body class="swagger-section"> <div id="message-bar" class="swagger-ui-wrap"> </div> <div id="swagger-ui-container" class="swagger-ui-wrap"></div> <script type="text/javascript"> $(function () { new SwaggerUi({ url: '<%= application.getContextPath() %>/api/swagger', dom_id: 'swagger-ui-container', swaggerRequstHeaders: 'application/json', // if you don't want to use it add .json to the url sorter: 'alpha' }).load(); }); </script> </body> </html>
All the work is done by SwaggerUi
class provided by swagger-ui module. You see however we rely on JSP to set the context path dynamically which is a nice feature for web applications.
Side note: we suppose our JAX-RS application has an @ApplicationPath
set to “api”.
Test Swagger UI
To test it I personally used tomee embedded maven plugin:
<plugin> <!-- mvn tomee-embedded:run to start testing against a real MySQL --> <groupId>org.apache.tomee.maven</groupId> <artifactId>tomee-embedded-maven-plugin</artifactId> <version>7.0.0-M1</version> <configuration> <context>/${project.artifactId}</context> <classpathAsWar>true</classpathAsWar> </configuration> </plugin>
And just run:
mvn tomee-embedded:run
Then you can go in http://localhost:8080/app/ and you should see something like:
Want more content ? Keep up-to-date on my new blog
Or stay in touch on twitter @rmannibucau
Hi Romain,
It not works for me :S.
Have you dealed with the following error when you added ApiListingResource to your Rest Application?
java.lang.NullPointerException: null
at io.swagger.jaxrs.config.SwaggerContextService.isScannerIdInitParamDefined(SwaggerContextService.java:236) ~[swagger-jaxrs-1.5.7.jar:1.5.7]
at io.swagger.jaxrs.listing.ApiListingResource.process(ApiListingResource.java:101) ~[swagger-jaxrs-1.5.7.jar:1.5.7]
at io.swagger.jaxrs.listing.ApiListingResource.getListingYaml(ApiListingResource.java:172) ~[swagger-jaxrs-1.5.7.jar:1.5.7]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_72]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_72]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
at org.apache.openejb.server.cxf.rs.PojoInvoker.performInvocation(PojoInvoker.java:43) ~[openejb-cxf-rs-7.0.0-M1.jar:7.0.0-M1]
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[cxf-core-3.1.3.jar:3.1.3]
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:200) ~[cxf-rt-frontend-jaxrs-3.1.3.jar:3.1.3]
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:99) ~[cxf-rt-frontend-jaxrs-3.1.3.jar:3.1.3]
at org.apache.openejb.server.cxf.rs.AutoJAXRSInvoker.invoke(AutoJAXRSInvoker.java:68) ~[openejb-cxf-rs-7.0.0-M1.jar:7.0.0-M1]
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) ~[cxf-core-3.1.3.jar:3.1.3]
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) ~[cxf-core-3.1.3.jar:3.1.3]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[cxf-core-3.1.3.jar:3.1.3]
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) ~[cxf-core-3.1.3.jar:3.1.3]
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251) ~[cxf-rt-transports-http-3.1.3.jar:3.1.3]
at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.doInvoke(CxfRsHttpListener.java:226) ~[openejb-cxf-rs-7.0.0-M1.jar:7.0.0-M1]
at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:94) ~[tomee-jaxrs-7.0.0-M1.jar:7.0.0-M1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[catalina.jar:8.0.29]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[catalina.jar:8.0.29]
Thanks
didnt see this one but used a previous version. Maybe try the 1.5.3.
Mmmm, I’ve changed the version and now I’m gettign this error:
16:37:50.395 [http-nio-7070-exec-2] ERROR o.a.c.i.AbstractFaultChainInitiatorObserver – Error occurred during error handling, give up!
org.apache.cxf.interceptor.Fault: io/swagger/jaxrs/ext/AbstractSwaggerExtension
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162) ~[cxf-core-3.1.5.jar:3.1.5]
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:128) ~[cxf-core-3.1.5.jar:3.1.5]
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:189) ~[cxf-rt-frontend-jaxrs-3.1.5.jar:3.1.5]
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:99) ~[cxf-rt-frontend-jaxrs-3.1.5.jar:3.1.5]
at org.apache.openejb.server.cxf.rs.AutoJAXRSInvoker.invoke(AutoJAXRSInvoker.java:68) ~[openejb-cxf-rs-7.0.0-M2.jar:7.0.0-M2]
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) ~[cxf-core-3.1.5.jar:3.1.5]
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96) ~[cxf-core-3.1.5.jar:3.1.5]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) ~[cxf-core-3.1.5.jar:3.1.5]
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-core-3.1.5.jar:3.1.5]
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:253) [cxf-rt-transports-http-3.1.5.jar:3.1.5]
at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.doInvoke(CxfRsHttpListener.java:237) [openejb-cxf-rs-7.0.0-M2.jar:7.0.0-M2]
at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:94) [tomee-jaxrs-7.0.0-M2.jar:7.0.0-M2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.32]
at org.apache.openejb.server.httpd.WebBeansFilter.doFilter(WebBeansFilter.java:52) [openejb-http-7.0.0-M2.jar:7.0.0-M2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.32]
at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:205) [rewrite-servlet-2.0.12.Final.jar:2.0.12.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.32]
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:201) [javamelody-1.59.0.jar:na]
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:178) [javamelody-1.59.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.32]
at org.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:122) [omnifaces-2.2.jar:2.2]
at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108) [omnifaces-2.2.jar:2.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.32]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [catalina.jar:8.0.32]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.32]
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44) [tomee-catalina-7.0.0-M2.jar:7.0.0-M2]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.32]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [catalina.jar:8.0.32]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.32]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [catalina.jar:8.0.32]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.32]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) [catalina.jar:8.0.32]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) [tomcat-coyote.jar:8.0.32]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) [tomcat-coyote.jar:8.0.32]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-coyote.jar:8.0.32]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-coyote.jar:8.0.32]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_72]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_72]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.32]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_72]
Caused by: java.lang.NoClassDefFoundError: io/swagger/jaxrs/ext/AbstractSwaggerExtension
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_72]
at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_72]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_72]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_72]
at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_72]
at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_72]
at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_72]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_72]
at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_72]
When I check my dependicies I see swagger-core-1.5.3.jar which is the container of that class…
Any idea? :_(
Thanks
should be swagger-jaxrs not core.
Sorry, I meant swagger-jaxrs :S. My dependency is like this:
io.swagger
swagger-jaxrs
1.5.3
javax.ws.rs
jsr311-api
javax.validation
validation-api
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
com.fasterxml.jackson.datatype
jackson-datatype-joda
com.fasterxml.jackson.datatype
jackson-annotations
com.fasterxml.jackson.core
jackson-core
com.fasterxml.jackson.datatype
jackson-databind
com.fasterxml.jackson.datatype
jackson-jaxrs-json-provider
org.javassist
javassist
org.reflections
reflections
org.slf4j
slf4j-api
create https://github.com/rmannibucau/swagger-in-tomee/blob/master/src/main/java/org/apache/cxf/jaxrs/swagger/JaxRs2Extension.java in your project, will work immediately I think.
Yeah, now it works :-D. So it’s a cxf issue, not?
TomEE/CXF. Reported it to CXF days/weeks ago but they didn’t fix their packaging yet.
Ok. Thanks for the help!
Hi Romain,
I have another “issue” with swagger, tomee and cxf.
I’m using my custom jackson ObjectMapper:
@ApplicationPath("resources")
public class RestServer extends Application {
private Set singletons = new HashSet();
public RestServer() {
singletons.add(new JacksonJsonProvider(JsonParser.defaultJacksonObjectMapper()));
singletons.add(new JAXRSBeanValidationInInterceptor());
}
@Override
public Set getSingletons() {
return singletons;
}
@Override
public Set<Class> getClasses() {
Set<Class> classes = new HashSet();
classes.add(CityService.class);
classes.add(BookingService.class);
classes.add(AuthenticationService.class);
classes.add(ApiListingResource.class);
return classes;
}
}
But when I add swagger to the pom, then the app starts to use the default ObjectMapper.
Any idea? I’ve seen in the logs the following:
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – Using writers:
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.johnzon.jaxrs.WadlDocumentMessageBodyWriter@31783b71
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – io.swagger.jaxrs.listing.SwaggerSerializers@5ee7720e
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.StringTextProvider@1abfe559
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – io.swagger.jaxrs.json.JacksonJsonProvider@2da7b325
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.johnzon.jaxrs.JsrProvider@4b445cc5
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.PrimitiveTextProvider@7fe8bf7
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.FormEncodingProvider@3e5df1a4
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.MultipartProvider@5127b417
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.SourceProvider@38ec6882
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.JAXBElementProvider@4bbefd5b
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider@76546d15
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider@11cfc7ef
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider@184dc330
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.BinaryDataProvider@74bf7da2
14:47:30.732 [http-nio-7070-exec-4] INFO OpenEJB.rs – org.apache.cxf.jaxrs.provider.DataSourceProvider@21569ae5
So I see that the app has registered the swagger jackson provider:
io.swagger.jaxrs.json.JacksonJsonProvider@2da7b325
how can I avoid the swagger jackson provider?
Thanks!!
I always skips providers scanning, it always creates a mess: https://github.com/rmannibucau/jwp/blob/master/src/main/webapp/WEB-INF/openejb-jar.xml#L6
Great! But still it’s not using my custom jackson objectmapper :S
Maybe.. are there a property to set the objectmapper?
Any idea?
Thanks!!
Did you set cxf.jaxrs.providers too?
Sorry! Now it works. I forgot to set the others providers (as the objectmapper) into the openejb-jar.xml
Thanks!
Good article !
I’ve just tried to do it in a EAR-WAR-EJB-JPA project. Swagger is correctly registred but EJB jar is not scanned. When I call swagger API, there is no paths 😦
My dependency graph:
EAR contains (EJB, WAR)
WAR contains (SWAGGER-UI, SWAGGER-JAXRS)
EJB contains (SWAGGER-JAXRS[provided], JPA)
only webapp are scanned you can add any EJB extending Application and returning their Class in getClasses() I think
Hi rmannibucau How can we restrict swagger in production environment alone? Do you have any suggetions?
A @WebFilter preventing swagger.json access for not allowed requests
Hi
While configuring swagger I am seeing an error in the bottom of the UI though it has no impact with functionality. While clicking on that error its showing {“schemaValidationMessages”:[{“level”:”error”,”message”:”Can’t read from file http://172.10.216.300:8080/myApp/swagger“}]}. I didn’t get this error for local environment. But its showing in QA. Any idea about this?
can be a lot of things like a proxy configuration, qa server conflict etc..