You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2022/10/31 19:00:41 UTC

[camel-quarkus] 10/19: Split MTOM tests into AWT and non-AWT modules

This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch 2.13.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit dfafbbef6af4d37cedf562b0004138b9e4393005
Author: Lukas Lowinger <ll...@redhat.com>
AuthorDate: Tue Oct 25 09:55:11 2022 +0200

    Split MTOM tests into AWT and non-AWT modules
---
 .../cxf-soap/cxf-soap-mtom-awt/README.adoc         |   4 +
 .../cxf-soap/cxf-soap-mtom-awt/pom.xml             | 150 +++++++++++++++++++++
 .../soap/mtom/awt/it/CxfSoapMtomAwtResource.java   |  88 ++++++++++++
 .../cxf/soap/mtom/awt/it/CxfSoapMtomAwtRoutes.java | 141 +++++++++++++++++++
 .../cxf/soap/mtom/awt/it/IImageService.java        |  33 +++++
 .../cxf/soap/mtom/awt/it/ImageService.java         |  63 +++++++++
 .../soap/mtom/awt/it/MtomAttachmentChecker.java    |  96 +++++++++++++
 .../src/main/resources/application.properties      |  19 +++
 .../cxf/soap/mtom/awt/it/CxfSoapMtomAwtIT.java     |  23 ++++
 .../cxf/soap/mtom/awt/it/CxfSoapMtomAwtTest.java   |  83 ++++++++++++
 .../src/test/resources/linux-image.png             | Bin 0 -> 38982 bytes
 integration-test-groups/cxf-soap/pom.xml           |   1 +
 12 files changed, 701 insertions(+)

diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/README.adoc b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/README.adoc
new file mode 100644
index 0000000000..a66940b720
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/README.adoc
@@ -0,0 +1,4 @@
+= Camel Quarkus CXF SOAP MTOM AWT tests
+
+Tests are not using any external SOAP services (eg. via testcontainers). They purely test if Camel Quarkus is able to send and consume messages with attachments (AWT Image) with both MTOM enabled/disabled.
+
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/pom.xml b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/pom.xml
new file mode 100644
index 0000000000..62b7ae9fd8
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/pom.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<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>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-build-parent-it</artifactId>
+        <version>2.13.1-SNAPSHOT</version>
+        <relativePath>../../../poms/build-parent-it/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-integration-test-cxf-soap-mtom-awt</artifactId>
+    <name>Camel Quarkus :: Integration Tests :: Cxf Soap Mtom AWT</name>
+    <description>Integration tests for Camel Quarkus CXF extension Mtom with AWT</description>
+
+    <dependencies>
+        <dependency><!-- for java.awt.Image -->
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-awt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-bean</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-cxf-soap</artifactId>
+        </dependency>
+
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>virtualDependencies</id>
+            <activation>
+                <property>
+                    <name>!noVirtualDependencies</name>
+                </property>
+            </activation>
+            <dependencies>
+                <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-bean</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-cxf-soap-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-direct-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtResource.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtResource.java
new file mode 100644
index 0000000000..fac4c2d1f9
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtResource.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URI;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.imageio.ImageIO;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.camel.ProducerTemplate;
+
+import static org.apache.camel.component.cxf.common.message.CxfConstants.OPERATION_NAME;
+
+@Path("/cxf-soap/mtom-awt")
+@ApplicationScoped
+public class CxfSoapMtomAwtResource {
+
+    @Inject
+    ProducerTemplate producerTemplate;
+
+    @Path("/upload")
+    @POST
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response upload(@QueryParam("imageName") String imageName, @QueryParam("mtomEnabled") boolean mtomEnabled,
+            byte[] image) throws Exception {
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(image)) {
+            final String response = producerTemplate.requestBodyAndHeader(
+                    "direct:" + mtomEndpoint(mtomEnabled),
+                    new Object[] { ImageIO.read(bais), imageName },
+                    OPERATION_NAME, "uploadImage", String.class);
+            return Response
+                    .created(new URI("https://camel.apache.org/"))
+                    .entity(response)
+                    .build();
+        }
+    }
+
+    @Path("/download")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    public Response download(@QueryParam("imageName") String imageName, @QueryParam("mtomEnabled") boolean mtomEnabled)
+            throws Exception {
+        final BufferedImage response = (BufferedImage) producerTemplate.requestBodyAndHeader(
+                "direct:" + mtomEndpoint(mtomEnabled),
+                imageName,
+                OPERATION_NAME,
+                "downloadImage", Image.class);
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            ImageIO.write(response, "png", baos);
+            byte[] bytes = baos.toByteArray();
+            return Response
+                    .created(new URI("https://camel.apache.org/"))
+                    .entity(bytes)
+                    .build();
+        }
+    }
+
+    private String mtomEndpoint(boolean mtomEnabled) {
+        return mtomEnabled ? "mtomAwtEnabledInvoker" : "mtomAwtDisabledInvoker";
+    }
+
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtRoutes.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtRoutes.java
new file mode 100644
index 0000000000..388a8cb093
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtRoutes.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.xml.ws.handler.Handler;
+
+import io.quarkus.runtime.LaunchMode;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.cxf.jaxws.CxfEndpoint;
+import org.apache.cxf.ext.logging.LoggingFeature;
+import org.apache.cxf.message.MessageContentsList;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+
+@ApplicationScoped
+public class CxfSoapMtomAwtRoutes extends RouteBuilder {
+
+    @Inject
+    @Named("loggingMtomAwtFeatureClient")
+    LoggingFeature loggingFeature;
+
+    @Override
+    public void configure() {
+
+        from("direct:mtomAwtEnabledInvoker")
+                .to("cxf:bean:soapMtomAwtEnabledClientEndpoint?dataFormat=POJO");
+
+        from("direct:mtomAwtDisabledInvoker")
+                .to("cxf:bean:soapMtomAwtDisabledClientEndpoint?dataFormat=POJO");
+
+        from("cxf:bean:soapMtomAwtEnabledServerEndpoint?dataFormat=POJO")
+                .to("direct:processAwtImage");
+
+        from("cxf:bean:soapMtomAwtDisabledServerEndpoint?dataFormat=POJO")
+                .to("direct:processAwtImage");
+
+        from("direct:processAwtImage")
+                .process("imageAwtServiceProcessor")
+                .recipientList((simple("bean:imageAwtService?method=${header.operationName}")));
+
+    }
+
+    @ApplicationScoped
+    @Named("imageAwtServiceProcessor")
+    static class ImageServiceProcessor implements Processor {
+        @Override
+        public void process(Exchange exchange) throws Exception {
+            String operationName = (String) exchange.getIn().getHeaders().get("operationName");
+            MessageContentsList list = (MessageContentsList) exchange.getIn().getBody();
+            if ("uploadImage".equals(operationName)) {
+                exchange.getIn().getHeaders().put("image", list.get(0));
+                exchange.getIn().getHeaders().put("imageName", list.get(1));
+                exchange.getIn().getHeaders()
+                        .put("operationName", "uploadImage(${header.image},${header.imageName})");
+            } else if ("downloadImage".equals(operationName)) {
+                exchange.getIn().setBody(list.get(0));
+            }
+        }
+
+    }
+
+    @Produces
+    @ApplicationScoped
+    @Named("loggingMtomAwtFeatureClient")
+    public LoggingFeature loggingFeature() {
+        final LoggingFeature result = new LoggingFeature();
+        result.setPrettyLogging(true);
+        return result;
+    }
+
+    @Produces
+    @ApplicationScoped
+    @Named
+    CxfEndpoint soapMtomAwtEnabledClientEndpoint() {
+        return commonCxfEndpoint(true, getServerUrl() + "/soapservice/mtom-awt-enabled-image-service");
+    }
+
+    @Produces
+    @ApplicationScoped
+    @Named
+    CxfEndpoint soapMtomAwtDisabledClientEndpoint() {
+        return commonCxfEndpoint(false, getServerUrl() + "/soapservice/mtom-awt-disabled-image-service");
+    }
+
+    @Produces
+    @ApplicationScoped
+    @Named
+    CxfEndpoint soapMtomAwtEnabledServerEndpoint() {
+        return commonCxfEndpoint(true, "/mtom-awt-enabled-image-service");
+    }
+
+    @Produces
+    @ApplicationScoped
+    @Named
+    CxfEndpoint soapMtomAwtDisabledServerEndpoint() {
+        return commonCxfEndpoint(false, "/mtom-awt-disabled-image-service");
+    }
+
+    CxfEndpoint commonCxfEndpoint(boolean mtomEnabled, String address) {
+        final CxfEndpoint result = new CxfEndpoint();
+        result.getFeatures().add(loggingFeature);
+        result.setServiceClass(IImageService.class);
+        result.setMtomEnabled(mtomEnabled);
+        result.setAddress(address);
+        List<Handler> handlers = new ArrayList<>();
+        handlers.add(new MtomAttachmentChecker(mtomEnabled));
+        result.setHandlers(handlers);
+        return result;
+    }
+
+    private static String getServerUrl() {
+        Config config = ConfigProvider.getConfig();
+        final int port = LaunchMode.current().equals(LaunchMode.TEST) ? config.getValue("quarkus.http.test-port", Integer.class)
+                : config.getValue("quarkus.http.port", Integer.class);
+        return String.format("http://localhost:%d", port);
+    }
+
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/IImageService.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/IImageService.java
new file mode 100644
index 0000000000..686c53bbc6
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/IImageService.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import java.awt.*;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+@WebService
+public interface IImageService {
+
+    @WebMethod
+    Image downloadImage(String name);
+
+    @WebMethod
+    String uploadImage(Image image, String name);
+
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/ImageService.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/ImageService.java
new file mode 100644
index 0000000000..aa0f0ab5c4
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/ImageService.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import java.awt.*;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ApplicationScoped
+@Named("imageAwtService")
+public class ImageService implements IImageService {
+
+    public static final String MSG_SUCCESS = "Upload Successful";
+    private static final Logger log = LoggerFactory.getLogger(ImageService.class);
+
+    private final Map<String, Image> imageRepository;
+
+    public ImageService() {
+        imageRepository = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public Image downloadImage(String name) {
+        final Image image = imageRepository.get(name);
+        if (image == null) {
+            throw new IllegalStateException("Image with name " + name + " does not exist.");
+        }
+        return image;
+    }
+
+    @Override
+    public String uploadImage(Image image, String name) {
+
+        log.info("Upload image: " + image + " with name: " + name);
+
+        if (image != null && name != null && !"".equals(name)) {
+            imageRepository.put(name, image);
+            return MSG_SUCCESS;
+        }
+        throw new IllegalStateException("Illegal Data Format.");
+    }
+
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/MtomAttachmentChecker.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/MtomAttachmentChecker.java
new file mode 100644
index 0000000000..a9be402aaa
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/MtomAttachmentChecker.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPException;
+import javax.xml.ws.WebServiceException;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Asserts whether the attachment is present where expected (inline or multipart body) throws an IllegalStateException
+ * to signal that something is wrong.
+ */
+public class MtomAttachmentChecker implements SOAPHandler<SOAPMessageContext> {
+    boolean mtomEnabled;
+
+    public MtomAttachmentChecker(boolean mtomEnabled) {
+        this.mtomEnabled = mtomEnabled;
+    }
+
+    static boolean walk(String localName, NodeList nodes) {
+        boolean found = false;
+        for (int i = 0; i < nodes.getLength(); i++) {
+            Node n = nodes.item(i);
+            if (localName.equals(n.getLocalName())) {
+                found = true;
+                break;
+            } else if (!found) {
+                found = walk(localName, n.getChildNodes());
+            }
+        }
+
+        return found;
+    }
+
+    @Override
+    public boolean handleMessage(SOAPMessageContext msgContext) {
+        try {
+            SOAPEnvelope envelope = msgContext.getMessage().getSOAPPart().getEnvelope();
+            SOAPBody body = envelope.getBody();
+            boolean found = walk("Include", body.getChildNodes());
+            if (mtomEnabled) {
+                // skip those messages which don't have attachments
+                boolean skip = walk("uploadImageResponse", body.getChildNodes()) || walk("downloadImage", body.getChildNodes());
+                if (!skip && !found) {
+                    throw new IllegalStateException("The SOAP message should contain an <xop:Include> element");
+                }
+            } else if (found) {
+                throw new IllegalStateException("The SOAP message shouldn't contain an <xop:Include> element");
+            }
+
+        } catch (SOAPException ex) {
+            throw new WebServiceException(ex);
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean handleFault(SOAPMessageContext context) {
+        return true;
+    }
+
+    @Override
+    public void close(MessageContext context) {
+    }
+
+    @Override
+    public Set<QName> getHeaders() {
+        return Collections.emptySet();
+    }
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/resources/application.properties b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/resources/application.properties
new file mode 100644
index 0000000000..574727024a
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/main/resources/application.properties
@@ -0,0 +1,19 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+quarkus.cxf.path=/soapservice
+quarkus.native.resources.includes = wsdl/*.wsdl
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtIT.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtIT.java
new file mode 100644
index 0000000000..5920b37eb5
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtIT.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class CxfSoapMtomAwtIT extends CxfSoapMtomAwtTest {
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtTest.java b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtTest.java
new file mode 100644
index 0000000000..ba52a03771
--- /dev/null
+++ b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/java/org/apache/camel/quarkus/component/cxf/soap/mtom/awt/it/CxfSoapMtomAwtTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.cxf.soap.mtom.awt.it;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import io.quarkus.test.junit.DisabledOnIntegrationTest;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.hamcrest.CoreMatchers;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+@QuarkusTest
+class CxfSoapMtomAwtTest {
+
+    @DisabledOnIntegrationTest("https://github.com/apache/camel-quarkus/issues/4208")
+    @ParameterizedTest
+    @ValueSource(booleans = { true, false })
+    public void uploadDownloadMtom(boolean mtomEnabled) throws IOException {
+        byte[] imageBytes = CxfSoapMtomAwtTest.class.getClassLoader().getResourceAsStream("linux-image.png").readAllBytes();
+        String imageName = "linux-image-name";
+        RestAssured.given()
+                .contentType(ContentType.BINARY)
+                .queryParam("imageName", imageName)
+                .queryParam("mtomEnabled", mtomEnabled)
+                .body(imageBytes)
+                .post("/cxf-soap/mtom-awt/upload")
+                .then()
+                .statusCode(201)
+                .body(CoreMatchers.equalTo(ImageService.MSG_SUCCESS));
+        byte[] downloadedImageBytes = RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .queryParam("imageName", imageName)
+                .queryParam("mtomEnabled", mtomEnabled)
+                .post("/cxf-soap/mtom-awt/download")
+                .then()
+                .statusCode(201)
+                .extract().asByteArray();
+
+        try (ByteArrayInputStream imageBais = new ByteArrayInputStream(
+                imageBytes); ByteArrayInputStream downloadedImageBais = new ByteArrayInputStream(downloadedImageBytes)) {
+            Assertions.assertTrue(bufferedImagesEqual(ImageIO.read(imageBais),
+                    ImageIO.read(downloadedImageBais)), "Uploaded image should match downloaded");
+        }
+    }
+
+    // copied from https://stackoverflow.com/a/15305092
+    boolean bufferedImagesEqual(BufferedImage img1, BufferedImage img2) {
+        if (img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight()) {
+            for (int x = 0; x < img1.getWidth(); x++) {
+                for (int y = 0; y < img1.getHeight(); y++) {
+                    if (img1.getRGB(x, y) != img2.getRGB(x, y))
+                        return false;
+                }
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/resources/linux-image.png b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/resources/linux-image.png
new file mode 100644
index 0000000000..17d7bfef0d
Binary files /dev/null and b/integration-test-groups/cxf-soap/cxf-soap-mtom-awt/src/test/resources/linux-image.png differ
diff --git a/integration-test-groups/cxf-soap/pom.xml b/integration-test-groups/cxf-soap/pom.xml
index 6df75158f3..f5c1514e5e 100644
--- a/integration-test-groups/cxf-soap/pom.xml
+++ b/integration-test-groups/cxf-soap/pom.xml
@@ -39,6 +39,7 @@
         <!-- extensions a..z; do not remove this comment, it is important when sorting via  mvn process-resources -Pformat -->
         <module>cxf-soap-client</module>
         <module>cxf-soap-mtom</module>
+        <module>cxf-soap-mtom-awt</module>
         <module>cxf-soap-server</module>
         <module>cxf-soap-ws-security-client</module>
         <module>cxf-soap-ws-security-server</module>