quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.83k stars 2.7k forks source link

Error when compiling native Quarkus with version 3.16.1 #44562

Open cesarjv opened 4 days ago

cesarjv commented 4 days ago

Good morning, I am currently working with Quarkus and I have the following error when running the native compilation, the error seems to be associated with a particular class that loads the SSL configuration to call a REST endpoint, the first solution was to add an argument in the native compilation command through the application.properties, however, this failed and now I have the following error:

Error: Discovered unresolved type during parsing: org.apache.commons.logging.LogFactory. This error is reported at image build time because class org.apache.http.conn.ssl.AbstractVerifier is registered for linking at image build time by command line and command line.
Error encountered while parsing com.tmve.subscriber.ms.route.ConfigureSsl.setupSSLContext(ConfigureSsl.java:26)
Parsing context:
   at com.tmve.subscriber.ms.route.RestRoute.configure(RestRoute.java:66)
   at org.apache.camel.builder.RouteBuilder.checkInitialized(RouteBuilder.java:809)
   at root method.(Unknown Source)

Detailed message:

com.oracle.svm.core.util.UserError$UserException: Discovered unresolved type during parsing: org.apache.commons.logging.LogFactory. This error is reported at image build time because class org.apache.http.conn.ssl.AbstractVerifier is registered for linking at image build time by command line and command line.
Error encountered while parsing com.tmve.subscriber.ms.route.ConfigureSsl.setupSSLContext(ConfigureSsl.java:26)
Parsing context:
   at com.tmve.subscriber.ms.route.RestRoute.configure(RestRoute.java:66)
   at org.apache.camel.builder.RouteBuilder.checkInitialized(RouteBuilder.java:809)
   at root method.(Unknown Source)

Detailed message:

        at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.UserError.abort(UserError.java:85)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FallbackFeature.reportAsFallback(FallbackFeature.java:248)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:814)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:592)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:550)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:539)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:721)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:143)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:98)
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Discovered unresolved type during parsing: org.apache.commons.logging.LogFactory. This error is reported at image build time because class org.apache.http.conn.ssl.AbstractVerifier is registered for linking at image build time by command line and command line.
Error encountered while parsing com.tmve.subscriber.ms.route.ConfigureSsl.setupSSLContext(ConfigureSsl.java:26)

For this development I am using Quarkus with Apache Camel and these are my main classes:

ResRoute

package com.tmve.subscriber.ms.route;

import com.tmve.subscriber.ms.beans.BeanDate;
import com.tmve.subscriber.ms.beans.request.Request;
import com.tmve.subscriber.ms.beans.response.Response;
import com.tmve.subscriber.ms.exceptions.InvalidRequestException;
import com.tmve.subscriber.ms.processor.*;
import jakarta.enterprise.context.ApplicationScoped;
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.bean.validator.BeanValidationException;
import org.apache.camel.model.rest.RestBindingMode;
import org.apache.camel.model.rest.RestParamType;
import org.apache.http.conn.HttpHostConnectException;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@ApplicationScoped
public class RestRoute extends RouteBuilder {
    @ConfigProperty(name = "client.idp")
    String urlIdp;

    @ConfigProperty(name = "descripcion.servicio")
    String descriptionService;

    private ConfigureSsl configureSsl;

    private static final String SALIDA_BSS_EXCEPTION = "Salida del microservicio GetActivateSessionByIp ${body}";
    private static final String MSG_EXCEPTION = "Descripcion de la Exception: ${exception.message}";

    private static final String DATE_LOG = "[${bean:BeanDate.getCurrentDateTime()}] ";

    public RestRoute() {
        configureSsl = new ConfigureSsl();
    }
    @Override
    public void configure() throws Exception {

        BeanDate beanDate= new BeanDate();
        getContext().getRegistry().bind("BeanDate", beanDate);

        restConfiguration().bindingMode(RestBindingMode.json).dataFormatProperty("json.in.disableFeatures","FAIL_ON_UNKNOWN_PROPERTIES")
                /*.clientRequestValidation(true) */
                .apiProperty("api.title","GetActiveSessionByIp")
                .apiProperty("api.description",descriptionService)
                .apiProperty("api-version","1.0.0")
                .apiProperty("cors","true");
        rest("/api")
                .produces("application/json")
                .consumes("application/json")
                .post("/v1/getActiveSessionByIp")
                .type(Request.class)
                .param().name("x-transaction-id").type(RestParamType.header).required(true).endParam()
                .outType(Response.class)
                .param().name("Response").type(RestParamType.body).description("Parametros de Salidas")
                .required(true)
                .endParam().to("direct:pipeline");
                from("direct:pipeline")
                        .doTry()
                            .log(DATE_LOG+ "Valor Header x-transaction-id: ${header.x-transaction-id}")
                            .log(DATE_LOG+ "Valor Header x-token: ${header.x-token}")
                            .log(DATE_LOG+ "Valor Header x-user: ${header.x-user}")
                            .process(new ValidateHeaderFieldProcessor())
                            .to("bean-validator:validateRequest")
                            .log(DATE_LOG+ "Datos de Entrada API GetActiveSessionVyIp: ${body}")
                            .process(new GetActiveSessionByIpReqProcess())
                            .to(configureSsl.setupSSLContext(getCamelContext(), urlIdp))
                            .choice()
                            .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(200))
                                .process(new GetActiveSessionByIpResProcess())
                                .log(DATE_LOG+ "Datos de Salida API GetActiveSessionByIp: ${exchangeProperty[jsonResponse]}")
                            .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(404))
                                .process(new NotFoundDataExcepcionProcessor())
                                .log(DATE_LOG+ "Datos de Salida API GetActiveSessionByIp: ${exchangeProperty[jsonResponse]}")
                            .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(406))
                                .process(new NotAcceptedResExceptionProcess())
                                .log(DATE_LOG+ "Datos de Salida API GetActiveSessionByIp: ${exchangeProperty[jsonResponse]}")
                            .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(500))
                                .process(new InternalErrorResProcess())
                                .log(DATE_LOG+ "Datos de Salida API GetActiveSessionByIp: ${exchangeProperty[jsonResponse]}")
                            /*.log(DATE_LOG+ "Datos de Salida del MS: ${body}") */
                            .end()
                        .endDoTry()
                        .doCatch(BeanValidationException.class)
                            .process(new InvalidRequestExceptionProcessor())
                            .log(DATE_LOG+MSG_EXCEPTION)
                            .log(DATE_LOG+SALIDA_BSS_EXCEPTION)
                        .doCatch(InvalidRequestException.class)
                            .process(new InvalidRequestExceptionProcessor())
                            .log(DATE_LOG+MSG_EXCEPTION)
                            .log(DATE_LOG+SALIDA_BSS_EXCEPTION)
                        .doCatch(HttpHostConnectException.class)
                            .process(new TimeoutExceptionProcessor())
                            .log(DATE_LOG+MSG_EXCEPTION)
                            .log(DATE_LOG+SALIDA_BSS_EXCEPTION)
                        .doCatch(Exception.class)
                        .process(new ExceptionProcessor())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
    }
}

ConfigureSsl

package com.tmve.subscriber.ms.route;

import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.component.http.HttpComponent;
import org.apache.camel.support.jsse.KeyManagersParameters;
import org.apache.camel.support.jsse.KeyStoreParameters;
import org.apache.camel.support.jsse.SSLContextParameters;
import org.apache.camel.support.jsse.TrustManagersParameters;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.eclipse.microprofile.config.ConfigProvider;

@Slf4j
@SuppressWarnings({})
@ApplicationScoped
public class ConfigureSsl {

    private String password = ConfigProvider.getConfig().getValue("client.password", String.class);
    private String resource = ConfigProvider.getConfig().getValue("client.file", String.class);

     public Endpoint setupSSLContext(CamelContext camelContext, String url) throws Exception {

            KeyStoreParameters keyStoreParameters = new KeyStoreParameters();
            keyStoreParameters.setResource(resource);
            keyStoreParameters.setPassword(password);

            KeyManagersParameters keyManagersParameters = new KeyManagersParameters();
            keyManagersParameters.setKeyStore(keyStoreParameters);
            keyManagersParameters.setKeyPassword(password);

            TrustManagersParameters trustManagersParameters = new TrustManagersParameters();
            trustManagersParameters.setKeyStore(keyStoreParameters);

            SSLContextParameters sslContextParameters = new SSLContextParameters();
            sslContextParameters.setKeyManagers(keyManagersParameters);
            sslContextParameters.setTrustManagers(trustManagersParameters);

            HttpComponent httpComponent = camelContext.getComponent("https", HttpComponent.class);
            httpComponent.setSslContextParameters(sslContextParameters);
            httpComponent.setX509HostnameVerifier(new AllowAllHostnameVerifier());

            return httpComponent.createEndpoint(url);
        }

}

Application.Properties

quarkus.ssl.native=true
quarkus.http.ssl-port=${PORT-SSl:8080}
quarkus.http.insecure-requests=disabled
quarkus.http.ssl.certificate.key-store-file-type=JKS
quarkus.http.ssl.certificate.key-store-file=${UBICATION_CERTIFICATE_SSL:srvdevrma1.jks}
quarkus.http.ssl.certificate.key-store-password=${PASSWORD_CERTIFICATE_SSL:xxxxxx}
quarkus.http.cors=true
quarkus.jackson.timezone=${TIME_ZONE:GMT-4}
quarkus.http.read-timeout=${SERVICE_READ_TIMEOUT:30000}
path=/api/v1/getActiveSessionByIp
descripcion.servicio=Microservicio que ejecuta la busqueda de un numero movil a partir de una IP/Puerto en la plataforma de Trazabilidad de Red
#ssl client
client.password=venezuela
client.file=cert.jks

#endpoints
client.idp=${URL_IDP:https://10.229.75.36/getActiveSessionByIp?bridgeEndpoint=false&?throwExceptionOnFailure=false}
username.idp=${USERNAME_IDP:opngwvzl}
password.idp=${PASSWORD_IDP:xxxxxxxxx}
#Open telemetry
quarkus.application.name=GetActiveSessionByIp
quarkus.otel.exporter.otlp.traces.endpoint=${URL_JAEGER:http://172.28.2.107:4317}
quarkus.otel.enabled=true
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n

#Ruta OpenApi
#path.openapi=/api/getActivateSessionByIp/openapi/swagger-ui/

#Headersw
quarkus.http.header."X-Content-Type-Options".value=nosniff
quarkus.http.header."X-Frame-Options".value=DENY
quarkus.http.header."X-XSS-Protection".value=1; mode=block
quarkus.http.header."Expect-CT".value=report-only
quarkus.http.header."Permissions-Policy".value=geolocation=*, fullscreen=*
quarkus.http.header."Cache-Control".value=no-cache
quarkus.http.header."Content-Security-Policy".value=default-src 'self'; img-src *; style-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self'; font-src 'self'; frame-src 'self

#Report Jacoco
quarkus.jacoco.excludes=com/huawei/**

#path.openapi=/openapi.yaml
camel.rest.api-context-path=/api/v1/getActiveSessionByIp/openapi.yaml
quarkus.swagger-ui.urls.camel=/api/v1/getActiveSessionByIp/openapi.yaml

quarkus.swagger-ui.enable=true
quarkus.swagger-ui.path=/api/v1/getActiveSessionByIp/swagger-ui/
quarkus.swagger-ui.always-include=true

#Error Code
error.0.code=0
error.0.message=Transaccion Exitosa

error.101.code=101
error.101.message=Token invalido

error.102.code=102
error.102.message=Invalid request

error.103.code=103
error.103.message=Imposible identificar cliente con datos entregados

error.104.code=104
error.104.message=Error interno

error.105.code=105
error.105.message=Timeout

#native-build
quarkus.native.additional-build-args=--initialize-at-run-time=org.apache.http.conn.ssl.AllowAllHostnameVerifier,-march=compatibility,-H:IncludeResources=.*\\.jks

Initially use the following argument --initialize-at-run-time=org.apache.http.conn.ssl.AllowAllHostnameVerifier, for the quarkus.native.additional-build-args property

quarkus-bot[bot] commented 4 days ago

/cc @zakkak (native-image)

geoand commented 7 hours ago

Quarkus doesn't really have support for Apache HTTP Client, so things like this are expected in native mode. If you are willing to dig in, you might want to try making some changes to https://github.com/quarkusio/quarkus/blob/df40afda6c8fcb91cd57f64a3a956be71c7bcbe3/extensions/apache-httpclient/deployment/src/main/java/io/quarkus/apache/http/client/deployment/ApacheHttpClientProcessor.java