Is there a way to auto-generate a ZOHO-style documentation of my Jersey Rest Services? This is one of the best REST documentations I have seen so far. I'm open to alternatives.
Swagger also looks promising but I don't see how to generate it. It seems like it needs a YAML style documentation.
Can I generate it from javadoc somehow?
I'd prefer to generate the docs via Maven.
You can generate swagger-ui from Javadoc by using Enunciate, which has a Swagger module. First, you need to add the maven plugin to your pom file; e.g.
<plugin>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-maven-plugin</artifactId>
<version>${enunciate.version}</version>
<executions>
<execution>
<goals>
<goal>docs</goal>
</goals>
<configuration>
<configFile>enunciate.xml</configFile>
<docsDir>${project.build.directory}</docsDir>
</configuration>
</execution>
</executions>
</plugin>
where 'enunciate.xml' contains your project specific configurations and looks like this:
<enunciate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.0.0-M.3.xsd">
<application root="/rest" />
</enunciate>
Then run mvn package and it will generate Swagger documentation files from your Javadoc.
p.s. taken from my answer here.
Adding swagger to jersey based services is not too complicated.
See these detailed steps on how to go about it:
Hope that helps
You can use Swagger to document your REST API, it's not difficult to set up. There are some instructions here. To summarize:
Adding Swagger dependencies
Add the following dependency to your pom.xml:
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
Setting up Swagger
Add the following to your Application class (change the values according to your needs):
#ApplicationPath("/api")
public class MyApplication extends Application {
public MyApplication() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("io.swagger.resources,com.example.project");
beanConfig.setScan(true);
}
}
Build your project, start your server and access http://localhost:8080/app/api/swagger.json (the URL might be different in your environment) to get the JSON which documents your API.
Setting up Swagger UI
Download Swagger UI from GitHub and copy the content from the dist folder to your web content folder. I usually create a folder called api-docs to store all Swagger UI files.
Open Swagger UI's index.html and change the URL which refers to the swagger.json:
var swaggerUi = new SwaggerUi({
url: "http://localhost:8080/app/api/swagger.json",
dom_id: "swagger-ui-container"
});
Access http://localhost:8080/app/api-docs (the URL might be different in your environment). The Swagger UI with your API documentation should be there.
More information
You always can customize Swagger UI to fit your needs.
Swagger reads JAX-RS annotations to generate the documentation. Additionally, you can use Swagger annotations to improve it.
Related
I've been using Spring Cloud Contract to test the Producer Side. And now, I wanted to upload the stub.jar file to nexus, so my colleague could write some integration test against my producer. And I found the Spring Documentation hard to follow.
<!-- First disable the default jar setup in the properties section-->
<!-- we don't want the verifier to do a jar for us -->
<spring.cloud.contract.verifier.skip>true</spring.cloud.contract.verifier.skip>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>stubs</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/java</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**com/example/model/*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**com/example/model/*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/snippets/stubs</directory>
<outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/mappings</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}/src/test/resources/contracts</directory>
<outputDirectory>META-INF/${project.groupId}/${project.artifactId}/${project.version}/contracts</outputDirectory>
<includes>
<include>**/*.groovy</include>
</includes>
</fileSet>
</fileSets>
After I add the "skip" line to the pom, I found that stubs json never get generated.
I'm using Spring Cloud Contract 1.2.4, and I think there is only "stub" folder in the target, not a "snippets/stubs".
What files are required in the stub.jar for the Stub Runner to run it?
I've been using Spring Cloud Contract to test the Producer Side. And now, I wanted to upload the stub.jar file to nexus, so my colleague could write some integration test against my producer.
If you use the DSL there's nothing you need to do. Just do ./mvnw deploy and we will generate the fat jar and the stubs jar.
And I found the Spring Documentation hard to follow.
That's not really specific is it? What exactly is hard to follow?
After I add the "skip" line to the pom, I found that stubs json never get generated.
Which skip line? If you add <spring.cloud.contract.verifier.jar.skip>false</spring.cloud.contract.verifier.jar.skip> then we will disable only JAR creation.
I'm using Spring Cloud Contract 1.2.4, and I think there is only "stub" folder in the target, not a "snippets/stubs".
Are you even using Rest Docs? Where did you get the snippet from? From here https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_publishing_stubs_as_jars ? If you read the text over the snippet you'll see For both Maven and Gradle, the setup comes ready to work. However, you can customize it if you want to.. If you follow the step by step section of the documentation we describe the whole, most basic flow. Also there are multiple tutorials out there, including a very thorough one over here http://cloud-samples.spring.io/spring-cloud-contract-samples/workshops.html
What files are required in the stub.jar for the Stub Runner to run it?
We describe that in the documentation. If you want to use the classpath mapping read this section https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_classpath_scanning . Otherwise, we unpack and go through any WireMock Json file that we can parse.
Here you have a working example of manual creation of stubs jar - https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_with_restdocs . I think you should read the documentation from the beginning and follow the tutorials. Or tell us what exactly is unclear with the documentation that made you feel confused.
Eclipse makes working with multi module maven projects easy because you don't have to re-build and re-install a module before dependent modules will see changes to it. So you just change the code and eclipse updates the dependencies magically in the background.
I want to achieve this behaviour for acceptance testing as well.
I have
storage-service
storage-service-war
storage-service-acceptance-tests
If I use embedded jetty or tomcat to test inside the storage-service-war project then obviously code changes are immediately viewable in the tests, but I cannot see any way to achieve the same quick iteration of testing when testing from storage-service-acceptance-tests.
Every way I look at it it seems that I have to build storage-service-war and then use the artefact generated from that, but it seems like overkill when you only want to change one line.
Does anyone have a good method for doing this?
Cheers
Piers
So answering my own question :D The solution I came up with will not work on CI it will likely only work when doing a local build as it makes use of the relative paths of the projects. At the bottom I outline a more robust but more complex approach that should satisfy eclipse and CI.
I was looking at setting attachClasses to true for the war plugin configuration of the war project.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
You can then reference the jar in the dependent project as follows
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>storage-service-war</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
</dependency>
Then I was thinking I could run my tests from within the acceptance test module using embedded jetty or tomcat and pointing them to the web.xml defined in the war project using a relative path.
This works fine with maven via the commandline but fails in eclipse :(
The problem with this is that the jar produced by attach classes is not picked up by the eclipse m2e integration see -https://bugs.eclipse.org/bugs/show_bug.cgi?id=365419 unfortunately it wont be fixed.
So My solution for the moment is to manually add the storage-service-war project to my acceptance test project build path in eclipse. Its not great but it works
The above solution is a bit hacky but the alternative outlined is a bit more involved.
By splitting the project into the following I think it would be possible to have correct eclipse integration and projects that work on CI
storage-service
storage-service-core
storage-service-war
storage-service-acceptance-tests
storage-service-config
The core project contains the logic and source of the webapp and is of type jar, the config contains the web.xml and any other config files and is also of type jar. Then the acceptance-tests and war project are both of type war and serve merely to package the core project into a war and extract the config to the webapp/WEB-INF dir so that they may share a common setup.
I need to generate java code from jet templates using a maven project and it should be done outside eclipse environment, but so far i haven't figure out how to do this.
I'm using maven 3x and jet 1.1.x.
I've tried several approaches but none of them seems to work:
invoke library org.eclipse.emf.codegen.jet.JETCompiler. This library seems to have a strong dependency with eclipse's environment and for such reason it failed.
one of maven's jet plugin doesn't work neither and i'm using the same example as provided in the offical website ([tikal-maven-jet-plugin][1]), here's how it looks like:
http://network.tikalk.com/release/tikal-maven-jet-plugin/usage.html
Does anyone have an idea how to do this?
Thanks a lot,
Carlos
Because of the way JET works, it'll only actually be runnable inside an eclipse environment. However, it's actually possible to launch eclipse headlessly to run an ant build script, so you get the eclipse parts you need running, without the UI. In order to do this, you need to launch the org.eclipse.ant.core.antRunner application. There's some documentation on how to do that here: http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Ftasks%2FantRunner.htm
Once you've launched the antRunner application, you can use the JET ant tasks to compile your templates and run your transform: http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.jet.doc%2Freferences%2Fant%2FantTasks.xhtml
There are some important caveats about headless template compilation which are relevant if you're headlessly compiling eclipse plugins, documented here: http://wiki.eclipse.org/JET_FAQ_How_to_I_compile_JET_templates_in_a_headless_build
I'm not sure how well any of this integrated with Maven, but this seems to be the best approach from ant. If you're wanting to run a transform from Java, there's some information here: http://wiki.eclipse.org/JET_FAQ_How_do_I_run_a_JET_transformation_from_Java%3F. You will still need to be in an eclipse environment for it to work though.
The tikal-maven-jet-plugin worked for me.
Here's a sample of a JET file I used in src/main/templates/generator.jet, I don't use the EMF classes, just standard Map.
<%# jet class="TableModelGenerator" package="net.trajano.framework.tool" %>
<% java.util.Map meta = (java.util.Map)argument; %>
package <%=meta.get("PackageName")%>;
public class <%=meta.get("ClassName")%> {
}
The plugin configuration I used is
<plugin>
<groupId>com.tikal</groupId>
<artifactId>tikal-maven-jet-plugin</artifactId>
<version>0.4.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<includeTemplates>
<include>**/*.jet</include>
</includeTemplates>
</configuration>
</plugin>
I want to migrate my EE application to OSGi. my application consist of business libraries, database JPA/Entities and a REST/WS interfaces. it also has a web client.
I start by prototyping the structure and making all the interfaces and bundles talking to each other in OSGi clean way. I want to use a clean specification as much as possible without any specific vendor or framework.
I am using bnd maven plugin to generate the manifest and the declarative services. I want to make a call from my rest resources to an OSGI service (on another bundle) using injection like so:
#Path("some-resources")
#Component
public class SomeResources{
private SomeService service = null;
#Reference
public void setController(SomeService service) { // <- this is never called
this.service = service;
}
#GET
#Produces(javax.ws.rs.core.MediaType.APPLICATION_XML)
public Object getSomeService() { // <- called
try {
service.process("Hello World"); // <- Error null object
}
...
}
Can i annotate the resource with bnd #Component and can the #Resource be injected?
everything works fine but the service is always null.
What should be the way to declare my bundle for BND to make it a web/wab package?
I use maven bundle:
<packaging>bundle</packaging>
...
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>biz.aQute</groupId>
<artifactId>bndlib</artifactId>
<version>1.50.0</version>
</dependency>
</dependencies>
<configuration>
<supportedProjectTypes>
<supportedProjectType>ejb</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
<supportedProjectType>wab</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>jar</supportedProjectType>
</supportedProjectTypes>
<instructions>
<_include>-osgi.bundle</_include>
</instructions>
</configuration>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
<execution>
<id>bundle-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
...
with bnd instructions
Web-ContextPath: my-root-http/rest/
Service-Component: *
OSGi has a part of specification called Remote Services. In very short it works in the way that you can register services with special service-properties and based on the properties technologies should pick up your service and create an endpoint from them. It is not only about REST but about any technology that handles remote calls. You may find information in the OSGi Core specification under the "Remote Services" chapter.
Well it is a specification but who implements it? Currently there are two bigger projects I tried. CXF DOSGi and Eclipse ECF. They offer several technologies that support Remote Services Specification. CXF especially upports Jax-RS based on it's implementation on both server and client side.
As I did not want to use spring specific solutions inside OSGi I did not use CXF on the end but created my own solution. It is based on Jersey and the Remote Services specification. When an OSGi Service is specified with the service.exported.interfaces=* and the service.exported.configs=org.everit.osgi.remote.jersey it will create a rest endpoint under the /rest/ path with HttpService. Your bundle does not have to be a wab it can be a simple bundle.
I must mention that if you expose your services via any of the Remote Services implementation you should take the Jax-RS annotations into an interface that is implemented by your original class and expose your service based on that interface.
Instead of #Resource and #Component annotations inside OSGi I suggest that you should use Blueprint (part of OSGi spec) that is amazingly similar to Spring. Currently Apache Aries and Gemini Blueprint implements it. With blueprint you can easily create beans and wire them to each other. If register your remote service in this way you can set any of the property with the help of blueprint (just like the property of a bean in the spring applicationcontext.xml).
You can find a sample application that I made at https://source.everit.biz/svn/everit-osgi/trunk/samples/jaxrs/ (user/passwd: guest/guest). There is a guide that explains how this samples can be started and developed at http://cookbook.everit.org
I hope the sample application helps you to get started with the Remote Services specification chapter.
To see how to use JPA and Injection (Blueprint) you should check the OSGi compendium specification for possibilities and find the implementation you like. I also made a sample project based on blueprint and hibernate-jpa that you can find as the sibling of the sample url I already provided.
Update
There is also a JAXRS extender implementation I made at https://github.com/everit-org/osgi-remote-jersey. See the README for documentation. It is different from the first in the way that this works based on whiteboard service properties.
I have experienced a similar problem with OSGi, Declarative Services and Jersey.
A resource can be annotated with #Component and #Reference annotations. This will instruct DS to create an instance of SomeResource class and to inject a valid reference into this instance when all dependecies (references) are satisfied.
The reason why your references are null is because JAX-RS implementation will create a new instance of SomeResource class for each web request. This instance of SomeResource class is not the same as the one created by DS.
I solved this problem by making reference variable static with Java static keyword:
private static SomeService service = null;
This ensured that a dependency reference is tied to a class object instead to an instance and then all instances could see the injected value.
This solution introduced a new problem. This reference must be cleared on unbind event (when service becomes unavailable) because it will not be destroyed when an instance is destroyed.
The problem would be solved when the #Path annotated type would be registered as a service itself. With DS you can than just inject other services. I faced this problem myself nearly a year ago. Thats why I wrote a small OSGi JAX-RS Connector which gives you exactly what I have described. Give it a try if you like: https://github.com/hstaudacher/osgi-jax-rs-connector
I need to add a crypto provider to the embedded JBoss used by Seam for integration tests.
For the regular JBoss it's a simple matter, just drop the files into the /lib folder of the server instance. With the embedded JBoss, however, things seem to be different. I've tried putting the jars in /embedded-jboss/bootstrap/lib and /embedded-jboss but no change, the classes are not seen.
I've read http://community.jboss.org/wiki/EmbeddedAndJavaSE and also looked in the source of org.jboss.embedded.Bootstrap but I haven't found a way yet. The build is done with Maven if it matters.
Thanks a lot for any suggestions.
I found an answer in the meantime: they can be added to the classpath of the plugin that runs the tests, like below. Works for me.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- snip -->
<additionalClasspathElements>
<additionalClasspathElement>add/here/your/jar</additionalClasspathElement>
</additionalClasspathElements>