Quarkus Endpoints in dependency jars - quarkus

I have a quarkus application which has dependencies to another maven module within the same project
within that module are REST endpoints
For some strange reason i cannot access those endpoints tho.. It seems quarkus will only accept endpoints of java classes within the quarkus module, or am I mistaken?

I foudn a solution:
if yopu add the jandex, endpoiints of other modules are being scanned, and can thus be found :
<build>
<plugins>
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

You can do this by creating a dummy extended class:
Lets assume your imported jar has this pattern, app\proto-gen\1.0-SNAPSHOT\proto-gen-1.0-SNAPSHOT.jar
Add the below to application.properties,
quarkus.index-dependency.mygrpc.group-id=app
quarkus.index-dependency.mygrpc.artifact-id=proto-gen
#Singleton
MyGrpc extends XImplBase{
//your implementation
}
beans you extended/implemented in your current project will be started.

Check https://quarkus.io/guides/cdi-reference. You need to add a beans.xml to external models, create an index or reference the dependency using quarkus.index-dependency in the application.properties.
Then it will work when running tests or using the runner. But not in dev, because there is a probably in the current version (1.1.1Final). This problem has been fixed in the master, though, and will be available in the next release next month.
Please check ClassCastException in Quarkus multi-module project for more details.

Related

Spring boot: resolve JSPs from jar dependencies

Unfortunately haven't found an answer in official documentation. Maybe what I'm trying to do is not supported event by Tomcat, but still. Is it possible to make spring-boot/Tomcat to resolve JSP pages from .jar file that is in the classpath?
I have a spring-boot (2) application that is packed as a war file. There are a numerous jsp pages in 'webapp/view' folder, and appropriate MVC configuration:
#Configuration
public class MVCConf implements WebMvcConfigurer {
// ...
#Bean
public ViewResolver internalResourceViewResolver() {
return new InternalResourceViewResolver(){{
setPrefix("/view/");
setSuffix(".jsp");
setRedirectHttp10Compatible(false);
}};
}
// ...
}
All these pages are being resolved. Okay.
But. The project is a multi-module maven one. It supports builds with different dependencies (my own modules) depending on maven profiles.
I need to make application to resolve JSPs from those optional dependencies that are included into runtime as jars in a classpath.
And I'm getting Whitelabel error that says that JSP files can not be found.
Is it even possible to make it work? And if it is, than how?
P.S.: I have already tried to make some magic with copying JSPs into "root" spring-boot application itself and it works, but this way is dirty and tricky.
I don't think it is worth to publish the whole pom.xml, but here is the maven-dependency-plugin section that works in my case:
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<!-- this skip property is set by maven profile in same pom.xml - no magic here -->
<skip>${exclude.some_submodule}</skip>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>some_submodule</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<!-- there are webapp/view/*.jsp files in some_module's structure -->
<includes>view/**</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- ... -->
The only problem here is that it works only when you launch the executable .war. Launching this application from IDE (IntelliJ IDEA) need some additional steps to be made. And that's another one disadvantage of this solution, to my mind. The first one is a dirty pom.xml.
TL;DR
Solution:
BUT!. I have found another solution that is more suitable, I think.
Actually I have moved from Tomcat to Jetty, and solution above works fine even there. There's no need in hacking the build anymore.
Now I put my .jsp files into src/main/webapp/META-INF/resources/view/some_module folder in some_module dependency and resolve it by path 'some_module/someJsp' via standard Spring's #Controllers.
I apologize that I haven't found this topic earlier. Now this is a duplicate. But who knows, maybe someone will apply solution with maven dependency plugin.

Required to create Maven plugin or 'some kind of wrapper' or should I use a parent pom

We are using the frontend-maven-plugin in several (10+) projects.
These projects are build in combination with our own CMS. These projects are using a specific 'parent' in the pom, such as:
<parent>
<groupId>nl.companyname</groupId>
<artifactId>companyname-corporate-pom</artifactId>
<version>2.0.13</version>
</parent>
In this 'corporate pom', we have some predefined configuration and 'plugin management', such as:
<project.frontendmavenplugin.version>1.3</project.frontendmavenplugin.version>
<project.frontendmavenplugin.workingDirectory>./</project.frontendmavenplugin.workingDirectory>
<project.node.downloadRoot>http://nodejs.COMPANYURL.nl/dist/</project.node.downloadRoot>
<project.node.version>v6.9.1</project.node.version>
<project.yarn.version>v0.17.9</project.yarn.version>
<project.yarn.downloadRoot>http://yarnpkg.COMPANYURL.nl/</project.yarn.downloadRoot>
<project.npm.registryUrl>http://nexus.COMPANYURL.nl/content/groups/npm-all/</project.npm.registryUrl>
and
<build>
<pluginManagement>
<!-- Generic configuration for plugins used by (almost) all projects. -->
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${project.frontendmavenplugin.version}</version>
<executions>
<execution>
<id>install node and yarn</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<workingDirectory>${project.frontendmavenplugin.workingDirectory}</workingDirectory>
<nodeVersion>${project.node.version}</nodeVersion>
<nodeDownloadRoot>${project.node.downloadRoot}</nodeDownloadRoot>
<yarnVersion>${project.yarn.version}</yarnVersion>
<yarnDownloadRoot>${project.yarn.downloadRoot}</yarnDownloadRoot>
</configuration>
</execution>
etc.
This way we don't have to copy/manage all configuration in each project.
This works great.
But: we are now also creating more and more new applications (based on Spring Boot) which are independent from our CMS and where we cannot use this 'parent pom' because Spring Boot has it's own (spring-boot-starter-parent) and our 'corporate pom' also contains very specific plugins / configuration which only applies to our CMS (which we are not including in these Spring Boot projects).
So what I need is something more 'standalone' for the frontend-maven-plugin configuration (and maybe in the future more 'platform' independent config/plugins). As far as I know, it's not possible to have more then 1 parent, so are there any other options?
I thought of creating a new 'companyname-frontend-maven-plugin' which both contains the PluginManagement as all the (extendable) configuration for the Frontend Maven Plugin. But I don't know if this will work and also it's a lot of work creating and maintaining this in git / Jenkins etc.
Are there any other options I could look in to?
Thank you all for your time!
maybe you can use a profile.
You can create a "corporate" pom that inherit from spring-boot-starter-parent and that contains a maven profile with all the properties and plugins required by your cms. So, when you are working on the CMS you will enable the "cms-profile".
Kind regards.

TypeNotPresentExceptionProxy error at integration-test with maven-failsafe-plugin spring-boot 1.4

I'm getting ArrayStoreException: TypeNotPresentExceptionProxy when running integration-test with maven-failsafe-plugin and spring-boot 1.4.
You can see this error if you run joinfaces-example with
mvn -Pattach-integration-test clean install
I realized that the error does not occur if I change spring-boot-maven-plugin to run at pre-integration-test phase instead of package one.
More, this error started when I upgraded spring boot to 1.4. No error occurs if I change jsf-spring-boot-parent version to 2.0.0 which uses spring boot 1.3 version.
I actually found the answer in Spring Boot 1.4 release notes, short answer is that maven-failsafe-plugin is not compatible with Spring Boot 1.4's new executable layout. Full explanation below :
As of Failsafe 2.19, target/classes is no longer on the classpath and
the project’s built jar is used instead. The plugin won’t be able to
find your classes due to the change in the executable jar layout.
There are two ways to work around this issue:
Downgrade to 2.18.1 so that you use target/classes instead
Configure the spring-boot-maven-plugin to use a classifier for the
repackage goal. That way, the original jar will be available and used
by the plugin. For example :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
An alternative is documented here: https://github.com/spring-projects/spring-boot/issues/6254
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!--
Make failsafe and spring-boot repackage play nice together,
see https://github.com/spring-projects/spring-boot/issues/6254
-->
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
</configuration>
</plugin>
This worked better for me, because when I used the "exec" solution, Spring failed to find my configuration files when starting the container. Which could probably be fixed by adding some further configuration parameters, I suppose, but this solution works "out of the box" for me.

How to hot redeploy non-active maven project via jetty-maven-plugin

I'm trying to evaluate jetty for rapid development or project which is currently running on tomcat. My configuration looks like
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.3.v20140905</version>
<configuration>
<scanIntervalSeconds>3</scanIntervalSeconds>
<webApp>
<descriptor>${project.build.directory}/${project.build.finalName}/WEB-INF/web.xml</descriptor>
<resourceBases>
<directory>${basedir}/src/main/webapp</directory>
<directory>${basedir}/../SharedWeb/src/main/webapp</directory>
</resourceBases>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
<contextPath>/test</contextPath>
</webApp>
</configuration>
</plugin>
I have main war depending on SharedWeb war via war overlay mechanism. I specify resourceBases for both maven projects so changes in resources are scanned automatically and reloaded on the fly and all working fine. Also when I compile classes in main war, jetty restarts automatically, reloading the latest changes. But when I try to change any class in SharedWeb project and compile it, the class is not reloaded. I'm just wondering if there is a way to make embed jetty to reload classes from SharedWeb automatically? I understand that jetty-maven-plugin uses SharedWeb war from local maven repository, so I need to install SharedWeb artifact before I can see any changes. So I don't have high expectations, but maybe I'm missing something.
Ivan,
The plugin is using the classes and resources from your dependency
war, NOT from the that you have added. The
simply tells jetty to watch that location and redeploy if something in
it changes - it does NOT put it onto the classpath.
You need to tell jetty to use the classes and resources from your
dependency war's project, NOT the war artifact.
So do something like:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.3.v20140905</version>
<configuration>
<webApp>
<!-- tell jetty to use the classes from the dependency
webapp project directly -->
<extraClassPath>${basedir}/../SharedWeb/target/classes</extraClassPath>
<!-- tell jetty to use both this project's static
resources, and those of the dependency webapp project -->
<resourceBases>
<directory>${basedir}/src/main/webapp</directory>
<directory>${basedir}/../SharedWeb/src/main/webapp</directory>
</resourceBases>
</webApp>
<scanIntervalSeconds>3</scanIntervalSeconds>
<!-- tell jetty to watch the dependency webapp project classes
dir for changes -->
<scanTargets>
<scanTarget>${basedir}/../SharedWeb/target/classes/</scanTarget>
</scanTargets>
</configuration>
</plugin>
Jan
Since there doesn't seem to be a good prior answer that is specific enough for this question (aka <scanTarget>) I'll just post this new one and tweak the title to make it easier to find in the future.
What you are looking for is <scanTarget>, as that will allow you to customize the scanning locations for changed content that will trigger a hot redeploy.
The jetty-maven-plugin intentionally does not set this up for custom <resourceBases> as there are far to many legitimate use cases where this can cause aggressive / too often / or infinite redeploys. It was decided that it was best to break from "convention over configuration" for <scanTarget> entries and allow the developers to decide what should be scanned for changes.
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.3.v20140905</version>
<configuration>
...
<scanIntervalSeconds>3</scanIntervalSeconds>
<scanTargets>
<scanTarget>${basedir}/../SharedWeb/src/main/webapp/</scanTarget>
<scanTarget>${basedir}/../SharedWeb/target/classes/</scanTarget>
</scanTargets>
</configuration>
</plugin>

Configure Maven to use CXF wsdl2java with Basic Authentication

I have an application that needs to integrate with one of SharePoint's web services. This web service cannot be accessed freely and needs authentication.
As such, the standard wsdl2java Maven plugin in my application gives an HTTP 401 error when the generate-sources phase is executed.
Is there a way to setup Maven/POM so that I can provide a user/password that will generate the stubs?
I have come across some answers saying this is not possible but all answers are older than 1 year. I haven't found if Maven have issued an update on this. One option is to save a local copy of the WSDL (as suggested here) but I would like to avoid having local copies.
Because you mentioned CXF then I suppose you meant cxf-codegen-plugin. It's a bit of a hack but it works.
HTTP authentication credentials can be provided using java.net.Authenticator. One need to just define his own Authenticator class which overrides getPasswordAuthentication(..) method. Then it has to be set as default Authenticator. As far as I know it can't be done declaratively (for instance using environment properties) only programatically using Authenticator.setDefault(..).
In order to call Authenticator.setDefault(..) I would use CXF extension mechanism. Create separate maven project with similar class:
public class AuthenticatorReplacer {
public AuthenticatorReplacer(Bus bus) {
java.net.Authenticator.setDefault(new java.net.Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("test", "test123"
.toCharArray());
}
});
}
}
and file src\main\resources\META-INF\cxf\bus-extensions.txt with contents:
org.example.AuthenticatorReplacer::false
Then add newly created project as a dependency to cxf-codegen-plugin:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${project.version}</version>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>cxf-authenticator-replacer</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
...
</plugin>
This way AuthenticatorReplacer is initialized by CXF extension mechanism and replaces default Authenticator with ours.
An clean alternative to #Dawid Pytel's solution would be to run this class during lifecycle of wsdl class auto generation:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>path.to.AuthenticatorReplacer</mainClass>
</configuration>
</plugin>
Important: your AuthenticatorReplacer has to be a main(String[] args) class and running the code inside.
I verified that Dawid's solution works. Alternatively, you can use SoapUI to pull down and cache the wsdl and then use SoapUi code generation support to use cxf to generate the code.
http://java.dzone.com/tips/generating-client-java-code
Dawid's solution works for me too. It is a little tricky though. In Eclipse, the pom.xml keeps complaining that "wsdl2java failed: Could not load extension class AuthenticatorReplacer". You have to ignore this error message and use the command line:
mvn generate-sources
The Java classes will then be generated successfully.

Resources