Swagger : Multiple locations for API not being picked up - java

In my project there are different packages containing Rest APIs
e.g.
com.mypackage.rest
com.mypackage2.rest
com.mypackage3.rest
I want to document all those.
I have a maven project having swagger plugin where in locations I am trying to specify multiple locations for Rest API as following
<locations>
com.mypackage.rest;
com.mypackage2.rest;
com.mypackage3.rest
</locations>
But when I do mvn clean install, it is not generating swagger json file.
PS. If I am using only one location, json file is being generated properly. Also if I try to put it as following, only last package json file is getting generated.
<locations>com</locations>
Need help!

<locations>com.mypackage.rest;com.mypackage2.rest;com.mypackage3.rest</locations> should do the trick, at least it works for me (version 3.1.x)
In the future (not yet released) the syntax will be:
<locations>
<location>com.mypackage.rest</location>
<location>com.mypackage2.rest</location>
<location>com.mypackage3.rest</location>
</locations>
See https://github.com/kongchen/swagger-maven-plugin/issues/328

Related

Using classes from /target

I am using JOOQ. JOOQ generates meta classes, using with database requests. It's recommended to generate classes into /target/generated-sources/jooq. But when I try to call these meta classes in code, they are not accessible.
Please, tell me what to do.
This is the default output location because the assumption is that most people are using Maven, and Maven will automatically include that path.
You can generate your classes anywhere you want including your own src directory, or whatever your IDE is defaulting to. For that, use the target configuration. Example from the manual:
<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.14.0.xsd">
<generator>
<target>
<packageName>org.jooq.your.packagename</packageName>
<directory>/path/to/your/dir</directory>
</target>
</generator>
</configuration>

Get (maven) artifact version at runtime of Java 9+ modular application

I have a Java 11 application which I develop using Maven and in the pom.xml I have a version declared.
<groupId>my.group.id</groupId>
<artifactId>artifact</artifactId>
<version>0.1.2.3</version>
I want to get this version at runtime e.g. using getClass().getPackage().getImplementationVersion() as it's described in this question. This works as long as I don't package my application as a modular runtime image using Jlink. Then I only get null returned from above call.
I package my application using:
jlink --output target/artifact-image --module-path target/dependencies --launcher MyApp=my.module.name/my.main.Class --add-modules my.module.name
Jlink has actually a parameter --version but this returns the Jlink version instead setting it for the generated artifact.
So, how can I get the version (of my Maven project) at runtime?
How to define it in the modular application?
How to get it into the modular application?
How to read it in the modular application?
I know I could define it in a resource file and simply read it from there, however I prefer to have it only in the pom.xml (= to have a single source of truth).
In the end I did this using the filtering function of the Maven Resources Plugin.
First, enable filtering in the pom.xml:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Then add a src/main/resources/my-version.properties file containig:
my.version=${project.version}
So you can use the following code in Java:
Properties myProperties = new Properties();
try {
myProperties.load(getClass().getResourceAsStream("/my-version.properties"));
} catch (IOException e) {
throw new IllegalStateException(e);
}
String theVersion = Objects.requireNonNull((String) myProperties.get("my.version"));
I had a similar problem in my last job. I needed to get the version for modules/jars that are not a direct dependency of the application, as well as the module's version itself. The classpath is assembled from multiple modules when the application starts, the main application module has no knowledge of how many jars are added later.
That's why I came up with a different solution, which may be a little more elegant than having to read XML or properties from jar files.
The idea
use a Java service loader approach to be able to add as many components/artifacts later, which can contribute their own versions at runtime. Create a very lightweight library with just a few lines of code to read, find, filter and sort all of the artifact versions on the classpath.
Create a maven source code generator plugin that generates the service implementation for each of the modules at compile time, package a very simple service in each of the jars.
The solution
Part one of the solution is the artifact-version-service library, which can be found on github and MavenCentral now. It covers the service definition and a few ways to get the artifact versions at runtime.
Part two is the artifact-version-maven-plugin, which can also be found on github and MavenCentral. It is used to have a hassle-free generator implementing the service definition for each of the artifacts.
Examples
Fetching all modules with coordinates
No more reading jar manifests or property files, just a simple method call:
// iterate list of artifact dependencies
for (Artifact artifact : ArtifactVersionCollector.collectArtifacts()) {
// print simple artifact string example
System.out.println("artifact = " + artifact);
}
A sorted set of artifacts is returned. To modify the sorting order, provide a custom comparator:
new ArtifactVersionCollector(Comparator.comparing(Artifact::getVersion)).collect();
This way the list of artifacts is returned sorted by version numbers.
Find a specific artifact
ArtifactVersionCollector.findArtifact("de.westemeyer", "artifact-version-service");
Fetches the version details for a specific artifact.
Find artifacts with matching groupId(s)
Find all artifacts with groupId de.westemeyer (exact match):
ArtifactVersionCollector.findArtifactsByGroupId("de.westemeyer", true);
Find all artifacts where groupId starts with de.westemeyer:
ArtifactVersionCollector.findArtifactsByGroupId("de.westemeyer", false);
Sort result by version number:
new ArtifactVersionCollector(Comparator.comparing(Artifact::getVersion)).artifactsByGroupId("de.", false);
Implement custom actions on list of artifacts
By supplying a lambda, the very first example could be implemented like this:
ArtifactVersionCollector.iterateArtifacts(a -> {
System.out.println(a);
return false;
});
Installation
Add these two tags to all pom.xml files, or maybe to a company master pom somewhere:
<build>
<plugins>
<plugin>
<groupId>de.westemeyer</groupId>
<artifactId>artifact-version-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<goals>
<goal>generate-service</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.westemeyer</groupId>
<artifactId>artifact-version-service</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
Feedback
It would be great if you could give the solution a try. Getting feedback about whether you think the solution fits your needs would be even better. So please don't hesitate to add a new issue on any of the github projects if you have any suggestions, feature requests, problems, whatsoever.
Licence
All of the source code is open source, free to use even for commercial products (MIT licence).

Load WSDl file from Spring Boot jar file?

Sorry if this is a duplicate, I looked at several other questions but none seemed to match or provide workable solutions.
Problem
I am writing a Spring Boot (v2.0.2) app, this app exposes a RESTful API which then calls into a WSDL service. I've generated the WSDL classes with Maven/jaxb plugin and everything works from my dev machine. When deployed to the server I get an error that the WSDL service class can not load the underlying WSDL file. The problem is that when the Java classes are generated it is using the full path from my dev machine (snippet from the generated service class)
try {
URL baseUrl;
baseUrl = com.mytest.WSDLService.class.getResource(".");
url = new URL(baseUrl, "/home/users/me/projects/wsdltest/wsdl/MyWSDL.wsdl");
} catch (MalformedURLException e) {
The WSDL file (MyWSDL.wsdl) is in the spring boot JAR file for my application, it is in a subdirectory off root called 'wsdl'
Question Is there a way that I can load this WSDL from the JAR file without having to modify the generated classes?
Ideal Solution I'm hoping to find a solution that doesn't make me modify the generated files (we intend to do this for several services), ideally I'd like a solution which can be done at build time (in the pom.xml?), if that's possible.
Solutions Tried
A post on here suggested using the "wsdlLocation" tag in my pom.xml and provide a explicit path to the WSDL file, e.g. <wsdlLocation>/wsdl/MyWSDL.wsdl</wsdlLocation>
Tried most of the solutions from this thread
Thanks in advance
I think I was able to find a solution thanks to this SO Thread. Evidently the answer depends on the version of the jaxws tool being used in maven (jaxws-maven-plugin). The project (which I inherited) explicitly asked for version 1.12 (which invoked JAX-WS RI 2.1.7-b01-), using this version of the tools I was able to use the '<wsdlLocation>classpath:wsdl/MyWSDL.wsdl</wsdlLocation>' solution in the thread mentioned. Once I noticed that the pom was using an explicit version I removed that the jaxws was updated (using JAX-WS RI 2.2.10) but then the 'classpath' solution stopped working. I switched to the other option mentioned in the thread '<wsdlLocation>/wsdl/MyWSDL.wsdl</wsdlLocation>'
I did a quick test and this seemed to have solved the problem (in both my dev machine and my test site).
Thank you

How to create service first soap webservice using spring-boot

We can see many tutorials that shows how to produce soap webservice using xsd in spring-boot. Is it possible to create soap webservice without xsd and from plain Java code using spring-boot-webservice module like we do using #webservice annotation in jax-ws
Guides like this start with an xsd file because they use xjc to create java classes from the XSD definition. xjc creates classes with JaxB annotations (javax.xml.bind.annotation). JaxB is an xml binding specification that has been part of the JDK since 1.6, and it requires that all types from the xsd exist as java classes.
I suggest that you do a tutorial that starts with an xsd an take a look at the auto generated classes. There is nothing to prevent you from writing you own classes instead of generating them from a wsdl, and if you don't refer to external schemas I prefer to do the code only approach (I hate xml configuration).
If you look at the tutorial, the gradle task "getJaxb" will create .java files into "build/generated-sources" compile them and copy them into "build/classes" if you copy the *.java files into "src/main/java" (keep the package structure) and delete delete/disable the "genJaxb" task in gradle, and delete your build folder, everything still works (it actually works better since you normally have red lines in your IDE because the XML beans don't exist until you run the generator the first time).
Now all you need to do is master the JaxB annotations, so you can write your own beans.

Modify Enunciate generated configuration file to use the latest jackson library for CXF

Enunciate generates the cxf-jaxrs-servlet.xml file automatically and specifies: org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider as the JAX-RS provider. This class has changed to com.fasterxml.jackson.jaxrs.JacksonJaxbJsonProvider in the latest Jackson library. How can I make Enunciate specify the new class as the JSON provider in the automatically generated file? Or can I make Enunciate to use a user provided XML file?
I had a similar issue and am using Maven with Spring. I was able to solve this by using the maven replacer plugin and setting it to overwrite the org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider in jaxrs:providers and replacing it with com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.
Unfortunately, there's not a good way to do that at the moment. We're tracking support for Jackson 2 at ENUNCIATE-719.

Categories