Configure Maven to use CXF wsdl2java with Basic Authentication - maven

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.

Related

Quarkus Endpoints in dependency jars

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.

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.

Spring Contract Maven Plugin pushStubsToScm does not work

I tried to use Spring Contract Maven Plugin in a producer side to upload the stubs jar and share it with consumers.
I am using Spring Cloud Contract 2.0.0.
I configured the spring-cloud-contract-maven-plugin in my project, the codes is uploaded to Github.
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<basePackageForTests>com.example.demo</basePackageForTests>
<baseClassMappings>
<baseClassMapping>
<contractPackageRegex>.*rest.*</contractPackageRegex>
<baseClassFQN>com.example.demo.RestVerifierBase</baseClassFQN>
</baseClassMapping>
</baseClassMappings>
<!-- We want to pick contracts from a Git repository -->
<!--<contractsRepositoryUrl>git://file://${project.basedir}/target/contract_git/</contractsRepositoryUrl>-->
<!-- Example of URL via git protocol -->
<!--<contractsRepositoryUrl>git://git#github.com:spring-cloud-samples/spring-cloud-contract-samples.git</contractsRepositoryUrl>-->
<!-- Example of URL via http protocol -->
<!--<contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-samples.git</contractsRepositoryUrl>-->
<contractsRepositoryUrl>git://https://github.com/hantsy/contracts-git.git</contractsRepositoryUrl>
<!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts -->
<contractDependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</contractDependency>
<!-- The mode can't be classpath -->
<contractsMode>REMOTE</contractsMode>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal -->
<goal>pushStubsToScm</goal>
</goals>
</execution>
</executions>
</plugin>
When I ran command mvn clean install -DskipTests -DcontractsRepositoryUsername=hantsy -DcontractsRepositoryPassword=mypassword and got the failure.
Caused by: org.eclipse.jgit.errors.TransportException: https://github.com/hantsy/contracts-git.git: Authentication is required but no CredentialsProvider has been registered
Update: If I set contractsMode to LOCAL, it will fail with downloading stubs jar error, maybe similar with this issue, in the new version 2.0.0, Spring Cloud contracts can not resolve jars from Local maven repos as expected when stubsMode is set to LOCAL.
Update 2: I also tried to add contractsRepositoryUsername and contractsRepositoryPassword in spring contract maven plugin config, it does not work.
contractsMode needs to be REMOTE. I've taken your example and it works well with:
<contractsRepositoryUrl>git://git#github.com:marcingrzejszczak/contracts-git.git</contractsRepositoryUrl>
<contractsMode>REMOTE</contractsMode>
with passing the credentials manually I see sth absolutely bizarre...
I see [INFO] Passed username and password - will set a custom credentials provider which means that username and password got passed and I'm using them. But actually what I get is Authentication is required but no CredentialsProvider has been registered, which makes no sense. Can you file another bug for that? The workaround is to use the agent.
UPDATE:
The issue got fixed here https://github.com/spring-cloud/spring-cloud-contract/issues/678

Kick off Spring Boot & make a call using a maven profile

I have an existing application which is a jetty app written in Java and managed with maven. There are a few basic tasks that can be run from the browser but mainly it runs all the tasks in one go when run from the command line (or Jenkins).
It does this by calling a specific Maven profile
so the maven command line call is
mvn clean install -P autorun
The autorun profile is
<profile>
<id>autorun</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<property name="runtime_classpath" refid="maven.runtime.classpath"/>
<java classname="com.app.tool.Client" >
<arg value="-h" />
<classpath>
<pathelement path="${runtime_classpath}"/>
</classpath>
</java>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
there is a main procedure in the Client class
public static void main(String... args) throws Exception { ...
which essentially
creates an org.eclipse.jetty.server.Server object
uses the war file to kick off the http server app
Uses a number of org.springframework.http.client.ClientHttpRequest objects to fire off a number of tasks using code along the lines of
ClientHttpRequest request = restTemplate
.getRequestFactory()
.createRequest(
new URI("http://localhost:8080/tool/spring/" + jobName),
HttpMethod.GET);
ClientHttpResponse clientHttpResponse = request.execute();
if (clientHttpResponse.getStatusCode().value() != HttpStatus.OK_200) {
throw new RuntimeException(...);
}
I am going to refactor the app now for various reasons. My aim is to keep the current design as, although it's main current use points more to a console app, I would like to make add some more useful interactive functionality.
So to finally get to the point, I have started re-writing the app as a Spring Boot application. I would like to still be able to fire off the jobs I want from the command line (and Jenkins). Is there a simple (& equivalent) way to do this with Spring Boot & Maven ? I am using Main to fire off the app so possibly I need to pass a switch into here
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringBootStartUpConfig.class, args);
}
I'm guessing that a lot of the code currently used to start the server can be dumped but I'm struggling to find the best way to achieve this ? (I'd prefer to use Maven as this is the core tool we are using but I can use Gradle if this is something that it is better at).
To run a spring boot application from command line you could include the spring boot maven plugin see reference here
Spring boot maven plugin
and then launch it from command line using
mvn spring-boot:run

Heroku DATABASE_URL as a JDBC Url for Maven

My apps on Heroku use a DATABASE_URL. This is simple to parse with Java into a JDBC URL with a user name and password. There's no issue there. However, I have a JOOQ generator and Flyway migrator that have maven plugins and I can't figure out how to get the JDBC URL, User Name, and Password that these plugins require into maven. So currently I do it on app startup which is not ideal. When my app starts I get the DATABASE_URL, parse it, then do the flyway migration and jOOQ code generation. But I would like this to happen during the actual build process, not during application startup.
Basically I need the Heroku Environment variable formatted like (postgres://user:pass#ec2-host:1234/path-to-db) to be accessible in maven as a property like this (jdbc:postgresql://ec2-host:1234?user=user&password=pass).
I think the solution may lie with the maven build helper plugin but I can't get the regex properties specification quite right.
Thanks
I have solved this thanks to heroku support. Lukas and Axel you may want to document this for any of your users that are using heroku, want to run your tools in their build (vs code startup), and do not want to hand maintain different environment variables.
We will be using the GMavin Plus Plugin to run some code to parse the DATABASE_URL environment variable into properties prior to running the flyway migration or jOOQ code generation.
First off you need to add Groovy as a dependency:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.3.9</version>
<scope>compile</scope>
</dependency>
Then the GMaven plus plugin:
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
</execution>
</executions>
<configuration>
<scripts>
<script><![CDATA[
URI dbUri = new URI(System.getenv("DATABASE_URL"));
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
int port = dbUri.getPort();
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ":" + port + dbUri.getPath();
project.properties['database.jdbcUrl']=dbUrl
project.properties['database.username']=username
project.properties['database.password']=password
]]></script>
</scripts>
</configuration>
</plugin>
Now you can use ${database.jdbcUrl}, ${database.username}, and ${database.password} in your flyway, jOOQ, or whatever else configurations.
There are probably myriad ways to solve this with Maven, but one option is to keep a single properties file in your /src/main/resources path, load it using the properties-maven-plugin (an example can be seen in the jOOQ-Spring example), and then compose URLs using the individual parts, e.g. jOOQ and Flyway:
<url>jdbc:postgresql://${db.host}:${db.port}/${db.database}</url>
<user>${db.username}</user>
<password>${db.password}</password>
Heroku:
<database_url>postgres://${db.username}:${db.password}#${db.host}:${db.port}/${db.database}</database_url>

Resources