Jax-WS Axis2 Proxy over SSL error using ProxySelector - ssl

In my project I have the following project structure:
I have a module that is producing a war file and can be deployed inside a Tomcat application server. This module has dependencies on Axis2 libraries:
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-http</artifactId>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-webapp</artifactId>
<type>war</type>
</dependency>
And this class contains an axis2.xml file in the conf folder under WEB-INF.
Now this module has a dependency on a unit module, that has the package type of a jar.
Now in my web-module, in the code for my stub I have following code:
GazelleObjectValidator.getInstance().validateObject();
The XcpdValidationService is a class in the jar module (dependency) and this method calls an external web service over SSL and using a proxy.
This web service client is generated by JAX WS RI
BUT this class doesn't use the axis2.xml configuration from the parent module and uses it's own axis configuration, being the default one, where my proxy is not configured...
#WebEndpoint(name = "GazelleObjectValidatorPort")
public GazelleObjectValidator getGazelleObjectValidatorPort() {
return super.getPort(new QName("http://ws.validator.sch.gazelle.ihe.net/", "GazelleObjectValidatorPort"), GazelleObjectValidator.class);
}
The method itself looks like this:
#WebMethod
#WebResult(name = "validationResult", targetNamespace = "")
#RequestWrapper(localName = "validateObject", targetNamespace = "http://ws.validator.sch.gazelle.ihe.net/", className = "net.ihe.gazelle.schematron.ValidateObject")
#ResponseWrapper(localName = "validateObjectResponse", targetNamespace = "http://ws.validator.sch.gazelle.ihe.net/", className = "net.ihe.gazelle.schematron.ValidateObjectResponse")
public String validateObject(
#WebParam(name = "base64ObjectToValidate", targetNamespace = "")
String base64ObjectToValidate,
#WebParam(name = "xmlReferencedStandard", targetNamespace = "")
String xmlReferencedStandard,
#WebParam(name = "xmlMetadata", targetNamespace = "")
String xmlMetadata)
throws SOAPException_Exception
;
My GazelleObjectValidatorService is generated by following plugin:
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-aar-maven-plugin</artifactId>
<version>${axis2.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>package-aar</id>
<phase>prepare-package</phase>
<goals>
<goal>aar</goal>
</goals>
</execution>
</executions>
<configuration>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources/wsdl</directory>
<outputDirectory>META-INF</outputDirectory>
<includes>
<include>**/*.xsd</include>
</includes>
</fileSet>
</fileSets>
<servicesXmlFile>${project.build.outputDirectory}/axis2/services.xml</servicesXmlFile>
<wsdlFile>${project.build.outputDirectory}/wsdl/ClientConnectorService.wsdl</wsdlFile>
</configuration>
</plugin>
I tried to override the transportSender in my axis2.xml configuration with my own defined MyCommonsHttpTransportSender:
<transportSender name="http"
class="eu.epsos.pt.cc.MyCommonsHTTPTransportSender">
<parameter name="PROTOCOL">HTTP/1.1</parameter>
<parameter name="Transfer-Encoding">chunked</parameter>
and
<transportSender name="https"
class="eu.epsos.pt.cc.MyCommonsHTTPTransportSender">
<parameter name="PROTOCOL">HTTP/1.1</parameter>
<parameter name="Transfer-Encoding">chunked</parameter>
</transportSender>
that knows about the proxy.
but unfortunately since the web service client is inside the jar that is a dependency of the war, it doesn't seem to use my axis2.xml configuration, but uses it's own axis configuration, which doesn't know about the proxy.
This causes the following error where you see clearly that it uses the default CommonsHTTPTransportSender and therefore throwing the error:
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:668)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.commons.httpclient.protocol.ReflectionSocketFactory.createSocket(ReflectionSocketFactory.java:140)
at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.createSocket(SSLProtocolSocketFactory.java:130)
at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:621)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:193)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.execute(AxisInvocationController.java:578)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.doInvoke(AxisInvocationController.java:127)
at org.apache.axis2.jaxws.core.controller.impl.InvocationControllerImpl.invoke(InvocationControllerImpl.java:93)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:373)
... 40 common frames omitted
Is there a way to let the WS client in the child jar make use of the same axis2 configuration of the parent module (that is a deployable war and has the axis2 dependencies?)
UPDATE:
My WAR file has an axis2 configuration, from the source code of this war, a service generated with wsimport is called which is in a JAR that is a dependency of the parent WAR. This service calls an external WebService and this happens over Axis (although doesn't use the axis2.xml configuration file, since this one is in the WEB-INF folder of the JAR.
Wouldn't there be any possibility to make the external WebService call in the JAR without Axis and use just JAXWS? This would solve my problems...

Axis2 provides a convenient method to configure the HTTP Transport. So, following from your sample code:
HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.new ProxyProperties();
proxyProperties.setProxyHostName("hostName");
proxyProperties.setProxyPort("hostPort");
proxyProperties.setUsername("User");
proxyProperties.setPassword("pw");
//set the properties
objectValidatorService.getServiceClient().getOptions().setProperty(HttpConstants.PROXY, proxyProperties);
The above wouldn't work for you because you're using the stock JAX-WS implementation, not the Axis2-specific client.
Based on your stacktrace, it appears you're connecting to a TLS-secured endpoint. There's a solution for that
I've done a lot of research, and there's no access to the underlying HTTPUrlConnection using stock JAX-WS. What we do have, is a way to set a custom SSLContextFactory. So we start by creating a custom factory, that will connect to the proxy first:
public class CustomSocketFactory extends SSLProtocolSocketFactory {
private static final CustomSocketFactory factory = new CustomSocketFactory();
static CustomSocketFactory getSocketFactory(){
return factory;
}
public CustomSocketFactory() {
super();
}
#Override
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) {
Socket socket = null;
try {
int proxyPort = 1000;
InetSocketAddress proxyAddr = new InetSocketAddress("proxyAddr", proxyPort);
Socket proxyConn = new Socket(new Proxy(Proxy.Type.SOCKS, proxyAddr));
proxyConn.connect(new InetSocketAddress("endHost", 443));
socket = (SSLSocket) super.createSocket(proxyConn, "proxyEndpoint", proxyPort, true);
} catch (IOException ex) {
Logger.getLogger(CustomSocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
return socket;
}
}
we'll now register this custom socket factory with the Apache HTTPClient runtime (Axis does not use the stock java HTTPUrlConnection, as is evidenced by your stacktrace):
Protocol.registerProtocol("https",new Protocol("https", new CustomSocketFactory(), 443));
This works only for TLS connections. (although, a custom socket factory is applicable to non-https endpoints also). You also need to set the timeout to 0 so we can guarantee that your overriden createSocket gets invoked

Related

Bean Validation on Jax-RS Resource stops working while using CDI on Apache TomEE 8.0.10

I'm having troubles getting bean validation to work with the following minimalised project consisting only of this three java files plus pom.xml. I'm using Apache TomEE 8.0.10.
LoginMessage.java
package org.example;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
#Getter
#Setter
#ToString
public class LoginMessage {
#NotBlank
private String username;
#NotBlank
private String password;
}
SessionService.java
package org.example;
import lombok.extern.java.Log;
import javax.enterprise.context.RequestScoped;
#Log
#RequestScoped
public class SessionService {
public void login(final LoginMessage loginMessage) {
log.info(loginMessage.toString());
}
}
SessionController.java
package org.example;
import lombok.extern.java.Log;
import javax.inject.Inject;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
#Log
#Path("/session")
public class SessionController {
#Inject
private SessionService sessionService;
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void postLoginMessage(#Valid final LoginMessage loginMessage) {
sessionService.login(loginMessage);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<groupId>org.example</groupId>
<artifactId>beanval</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
</project>
If you post an empty JSON object it ignores the #Valid annotation in SessionController#postLoginMessage() and directly outputs the log message containing the toString() content of the LoginMessage object through SessionService#login() method.
POST http://localhost:8080/beanval-1.0-SNAPSHOT/session
Content-Type: application/json
{
}
13-Mar-2022 01:30:39.700 INFORMATION [http-nio-8080-exec-6] SessionService.login LoginMessage(username=null, password=null)
If you remove or comment out the #RequestScoped annotation from SessionService and post the empty JSON-Object after restart of TomEE then bean validation works and logs:
13-Mar-2022 01:52:51.594 WARNUNG [http-nio-8080-exec-6] org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.toResponse Value (null) of SessionController.postLoginMessage.arg0.password: must not be blank
13-Mar-2022 01:52:51.595 WARNUNG [http-nio-8080-exec-6] org.apache.cxf.jaxrs.validation.ValidationExceptionMapper.toResponse Value (null) of SessionController.postLoginMessage.arg0.username: must not be blank
I would like to use CDI in combination with Bean-Validation in JAX-RS Resource.
What am I doing wrong?
Thanks in advance.
This appears to be a bug in OpenWebBeans or TomEE. So what's happening is the first the actual instance of the bean is managed by JAX-RS, and the second, the bean is managed by the CDI container. In the second case, there needs to be some sort of interceptor the invokes the Bean Validation framework.
I would start a discussion on the mailing list and open a bug on in the JIRA. If you can create a sample project that reproduces the problem it helps the devs out tremendously.
As a workaround, you can #Inject private Validator validator and if there are any constraint violations returned, throw new ConstraintViolationException(constraintViolations);.
After all to come up to some kind of a solution I will stop using bean validation at controller layer. It works at service layer and so I can continue to work on my web app.
The solution is using the #Valid annotation in SessionService#login() method and remove it from SessionController#postLoginMessage() method.
If it is really a bug in TomEE the alternative could also be to use another application server until it is fixed.

How do I use a Citrus mail endpoint in an Arquillian test on JEE server

I have a Java webapp where a REST call triggers a mail sent through a javax.mail.Session. The application is deployed as a .war archive that I want to test inside a JBoss EAP 7.2 server.
I am using Arquillian 1.5.0.Final and Citrus Framework version 2.8.0. My build system is Gradle 5.x and everything is using a Java 8 runtime.
I would like to create a Citrus mail endpoint and use Arquillian to provide this inside the JEE container. My experience with these frameworks is limited to a few days, so I'm starting with a sample application to gain more knowledge:
I have the following working against a simple web endpoint (The HelloServlet from https://guides.gradle.org/building-java-web-applications/):
#RunWith(Arquillian.class)
public class HelloServletTest {
#CitrusFramework
private Citrus citrusFramework;
#ArquillianResource
private URL baseUri;
private String serviceUri;
#Deployment(testable = false)
public static WebArchive createDeployment() {
final WebArchive war = ShrinkWrap.create(WebArchive.class)
.addClass(HelloServlet.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
// [...]
return war;
}
#Before
public void setUp() throws Exception {
serviceUri = new URL(baseUri, "hello").toExternalForm();
}
#Test
#CitrusTest
public void smokeTest(#CitrusResource TestDesigner designer) throws InterruptedException {
System.err.println("ServiceURI: " + serviceUri);
designer.send(serviceUri)
.message(new HttpMessage("?name=Jacob")
.method(HttpMethod.POST));
designer.receive(serviceUri).message(new HttpMessage("").status(HttpStatus.OK));
citrusFramework.run(designer.getTestCase());
}
}
I use #Deployment(testable=false) as this example runs a client-side test. However, my end goal is to use Citrus inside the container so my understanding is that I need to have #Deployment(testable=true). But when I run the test with testable=true a NPE is thrown:
java.lang.NullPointerException
at com.consol.citrus.annotations.CitrusAnnotations.injectAll(CitrusAnnotations.java:61)
at com.consol.citrus.arquillian.enricher.CitrusTestEnricher.enrich(CitrusTestEnricher.java:57)
at org.jboss.arquillian.junit.RulesEnricher.enrichInstances(RulesEnricher.java:85)
at org.jboss.arquillian.junit.RulesEnricher.enrichStatement(RulesEnricher.java:77)
[...]
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:103)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:90)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.createContext(ContainerEventController.java:128)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.createBeforeContext(ContainerEventController.java:114)
[...]
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.fireCustomLifecycle(EventTestRunnerAdaptor.java:159)
at org.jboss.arquillian.junit.Arquillian$7.evaluate(Arquillian.java:273)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
[...]
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
[...]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.lang.Thread.run(Thread.java:748)
My arquillian.xml is
<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<defaultProtocol type="Servlet 3.0"/>
<engine>
<property name="deploymentExportPath">build/deployments</property>
</engine>
<container qualifier="wildfly-managed" default="true">
</container>
<extension qualifier="citrus">
<property name="autoPackage">false</property>
<property name="citrusVersion">2.8.0</property>
</extension>
</arquillian>
My citrus-context.xml is
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:citrus-mail="http://www.citrusframework.org/schema/mail/config"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/mail/config http://www.citrusframework.org/schema/mail/config/citrus-mail-config.xsd">
<!-- Mail server mock -->
<citrus-mail:server id="mailServer"
auto-start="true"
port="2222"/>
</beans>
My questions are:
Does my approach make sense? Is it feasible to use Citrus and Arquillian in this way?
Is the NPE exception to be expected or am I missing some dependency or configuration?

Weblogic Jaxws deployment - class does not support JDK1.5

WebLogic Server Version: 10.3.6.0
Spring version: 3.2.1.RELEASE
Java JDK 1.6
I am trying to deploy a Spring application as WAR that uses jaxws into a Weblogic server.
The application works well with Jetty. However when deploying(I mean starting deployed app) Weblogic following exception occurs:
Caused By: java.lang.UnsupportedOperationException: This class does not support JDK1.5
at weblogic.xml.jaxp.RegistryTransformerFactory.setFeature(RegistryTransformerFactory.java:317)
at com.sun.xml.ws.util.xml.XmlUtil.newTransformerFactory(XmlUtil.java:392)
at com.sun.xml.ws.util.xml.XmlUtil.newTransformerFactory(XmlUtil.java:400)
at com.sun.xml.ws.util.xml.XmlUtil.<clinit>(XmlUtil.java:233)
at org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:36
.
maven pom.xml
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>org.jvnet.jax-ws-commons.spring</groupId>
<artifactId>jaxws-spring</artifactId>
<version>1.9</version>
</dependency>
Weblogic.xml
<weblogic-web-app>
<context-root>/MyApp</context-root>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
</container-descriptor>
</weblogic-web-app>
It is being fixed by changing weblogic.xml
<container-descriptor>
<prefer-web-inf-classes>false</prefer-web-inf-classes>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
<prefer-application-packages>
<package-name>com.sun.xml.ws.server.*</package-name>
</prefer-application-packages>
</container-descriptor>
And in init servlet (if you use the old style) you should change the way you acquire the context as:
private static WebApplicationContext context;
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
this.context = WebApplicationContextUtils.getWebApplicationContext(sc);
...
}
public static WebApplicationContext getApplicationContext(){
return context;
}
That fixes it

Read data from Redis to Flink

I have been trying to find a connector to read data from Redis to Flink. Flink's documentation contains the description for a connector to write to Redis. I need to read data from Redis in my Flink job. In Using Apache Flink for data streaming, Fabian has mentioned that it is possible to read data from Redis. What is the connector that can be used for the purpose?
We are running one in production that looks roughly like this
class RedisSource extends RichSourceFunction[SomeDataType] {
var client: RedisClient = _
override def open(parameters: Configuration) = {
client = RedisClient() // init connection etc
}
#volatile var isRunning = true
override def cancel(): Unit = {
isRunning = false
client.close()
}
override def run(ctx: SourceContext[SomeDataType]): Unit = while (isRunning) {
for {
data <- ??? // get some data from the redis client
} yield ctx.collect(SomeDataType(data))
}
}
I think it really depends on what you need to fetch from redis. The above could be used to fetch a message from a list/queue, transform/push and then delete it form the queue.
Redis also supports Pub/Sub, so it would possible to subscribe, grab the SourceConext and push messages downstream.
Currently, Flink Redis Connector is not available but it can be implemented by extending RichSinkFunction/SinkFunction class.
public class RedisSink extends RichSinkFunction<String> {
#Override
public void open(Configuration parameters) throws Exception {
//open redis connection
}
#Override
public void invoke(String map) throws Exception {
//sink data to redis
}
#Override
public void close() throws Exception {
super.close();
}
}
There's been a bit of discussion about having a streaming redis source connector for Apache Flink (see FLINK-3033), but there isn't one available. It shouldn't be difficult to implement one, however.
One of challenges in getting your Flink program to use Jedis to talk to Redis is getting the appropriate libraries into the JAR file you submit to Flink. Absent this, you will get call stacks indicating certain classes are undefined. Here is a snippet of a Maven pom.xml I created to move Redis and its dependent component, apache commons-pool2, into my JAR.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>unpack</id>
<!-- executed just before the package phase -->
<!-- https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/linking.html -->
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>org/apache/commons/**</includes>
</artifactItem>
<artifactItem>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>redis/clients/**</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Arquillian - How to debug managed Wildfly container

I am using Arquillian to write black box tests for my RESTful application. I am actually capable of debug the test classes, but unable to debug my application classes. I would like to know exactly how to do that.
My arquillian.xml:
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="jbossas-managed" default="true">
<configuration>
<property name="jbossHome">D:\desenv\arquivos\servidores\wildfly-9.0.1.Final-test</property>
<property name="allowConnectingToRunningServer">true</property>
<property name="javaVmArguments">-Dorg.apache.deltaspike.ProjectStage=IntegrationTest</property>
</configuration>
</container>
One of my test classes:
#RunAsClient
#RunWith(Arquillian.class)
public class AuthenticationBlackBoxTest extends AbstractBlackBoxTest {
#Test
public void testInvalidCredentials(#ArquillianResource URL baseURI) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(baseURI.toString()).path("api/v1/auth");
Response response = target.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(new Credentials("invalid", "invalid"), MediaType.APPLICATION_JSON));
Assert.assertEquals(401, response.getStatus());
response.close();
client.close();
}
#Test
public void testValidCredentials(#ArquillianResource URL baseURI) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(baseURI.toString()).path("api/v1/auth");
Entity<Credentials> credentialsEntity = Entity.entity(new Credentials("adm#adm.com", "123"), MediaType.APPLICATION_JSON);
Response response = target.request(MediaType.APPLICATION_JSON)
.post(credentialsEntity);
Assert.assertEquals(200, response.getStatus());
response.close();
client.close();
}
}
Inside arquillian.xml for javaVmArguments element add -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y.
Then in your favourite IDE you have to define a new Remote Debug configuration where you specify the host(localhost), port(8787). Place your break point, then run your test and finally start the remote debug. Official doc here.