luisgoncalves / xades4j

A Java library for XAdES signature services
GNU Lesser General Public License v3.0
111 stars 66 forks source link

JAXBException with newSigner method #263

Closed AndresN17 closed 2 years ago

AndresN17 commented 2 years ago

Hi, I don't use Java in a while but i found that is the best option for make xades-bes signature, I was triying to make it within a spring boot application, but it return this error:

[Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: jakarta/xml/bind/JAXBException] with root cause
java.lang.ClassNotFoundException: jakarta.xml.bind.JAXBException
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
        at java.base/java.lang.Class.getDeclaredConstructors0(Native Method) ~[na:na]
        at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3373) ~[na:na]
        at java.base/java.lang.Class.getDeclaredConstructors(Class.java:2555) ~[na:na]
        at com.google.inject.spi.InjectionPoint.forConstructorOf(InjectionPoint.java:299) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.ConstructorBindingImpl.create(ConstructorBindingImpl.java:121) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InjectorImpl.createUninitializedBinding(InjectorImpl.java:715) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:941) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:863) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:300) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:223) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InjectorImpl.getInternalFactory(InjectorImpl.java:949) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.FactoryProxy.notify(FactoryProxy.java:48) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.ProcessedBindingData.runCreationListeners(ProcessedBindingData.java:60) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:137) ~[guice-5.1.0.jar:na]
        at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110) ~[guice-5.1.0.jar:na]
        at com.google.inject.Guice.createInjector(Guice.java:87) ~[guice-5.1.0.jar:na]
        at com.google.inject.Guice.createInjector(Guice.java:69) ~[guice-5.1.0.jar:na]
        at com.google.inject.Guice.createInjector(Guice.java:59) ~[guice-5.1.0.jar:na]
        at xades4j.utils.XadesProfileCore.getInstance(XadesProfileCore.java:236) ~[xades4j-2.1.0.jar:na]
        at xades4j.production.XadesSigningProfile.newSigner(XadesSigningProfile.java:110) ~[xades4j-2.1.0.jar:na]
        at com.facturacion.facturacion.utils.SignerUtil.signDocument(SignerUtil.java:69) ~[classes/:na]
        at com.facturacion.facturacion.controllers.FacturaController.signFactura(FacturaController.java:25) ~[classes/:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]

I didn't paste all the error because the following is just spring and apache internal errors, It seems that is in the newSigner() method, but I don't find why. I search but only found that maybe is for JAXB is not in Java in version 9 and above, I use OpenJDK17. I add to the pom.xml all the solutions that I found (JAXB Versions) but still get the same error.

My code:

try {

                        Document doc = DocumentBuilderFactory
                                        .newInstance()
                                        .newDocumentBuilder()
                                        .parse(new File(inputSource));
                        Element el = doc.getDocumentElement();
                        DOMHelper.useIdAsXmlId(el);

                        KeyingDataProvider kp = FileSystemKeyStoreKeyingDataProvider
                                        .builder("pkcs12", keyPath, SigningCertificateSelector.single())
                                        .storePassword(new DirectPasswordProvider(password))
                                        .entryPassword(new DirectPasswordProvider(password))
                                        .fullChain(true)
                                        .build();

                        BasicSignatureOptions config = new BasicSignatureOptions();
                        config.includePublicKey(true);
                        config.includeSigningCertificate(SigningCertificateMode.SIGNING_CERTIFICATE);
                        config.signKeyInfo(true);

                        XadesSigner signer = new XadesBesSigningProfile(kp)
                                        .withBasicSignatureOptions(config)
                                        .withSignatureAlgorithms(new SignatureAlgorithms()
                                                        .withSignatureAlgorithm("RSA",
                                                                        XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1)
                                                        .withDigestAlgorithmForReferenceProperties(
                                                                        MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA1)
                                                        .withDigestAlgorithmForDataObjectReferences(
                                                                        MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA1))
                                        .newSigner();

                        DataObjectDesc obj = new DataObjectReference("#" + el.getAttribute("Id"))
                                        .withTransform(new EnvelopedSignatureTransform());

                        SignedDataObjects dataObjs = new SignedDataObjects().withSignedDataObject(obj);

                        signer.sign(dataObjs, el);
                        TransformerFactory tFactory = TransformerFactory.newInstance();
                        Transformer transformer = tFactory.newTransformer();
                        DOMSource source = new DOMSource(doc);
                        StreamResult result = new StreamResult(new File(outputSource));
                        transformer.transform(source, result);

                } catch (XadesProfileResolutionException x) {
                        System.out.println("Error: " + x);
                } catch (ParserConfigurationException p) {
                        System.out.println("Error: " + p);
                } catch (IOException i) {
                        System.out.println("Error: " + i);
                } catch (SAXException s) {
                        System.out.println("Error: " + s);
                } catch (XAdES4jException xa) {
                        System.out.println("Error: " + xa);
                } catch (TransformerException t) {
                        System.out.println("Error: " + t);
                }
AndresN17 commented 2 years ago

Well I updated the dependencies to the xades4j and it solve that problem, but now I'm getting another error:

Error: xades4j.utils.XadesProfileResolutionException: Unable to provision, see the following errors:

1) [Guice/ErrorInjectingConstructor]: NoClassDefFoundError: jakarta/activation/DataSource
  at DefaultSignedPropertiesMarshaller.<init>(DefaultSignedPropertiesMarshaller.java:52)
  while locating DefaultSignedPropertiesMarshaller
  at SignerBES.<init>(SignerBES.java:98)
      \_ for 8th parameter
  while locating SignerBES

Learn more:
  https://github.com/google/guice/wiki/ERROR_INJECTING_CONSTRUCTOR

1 error

======================
Full classname legend:
======================
DefaultSignedPropertiesMarshaller: "xades4j.xml.marshalling.DefaultSignedPropertiesMarshaller"
SignerBES:                         "xades4j.production.SignerBES"
========================
End of classname legend:
========================
luisgoncalves commented 2 years ago

Hi,

Which xades4j version are you using? There are tests running on Java 17 and everything is fine: https://github.com/luisgoncalves/xades4j/runs/7120234832

xades4j has its own dependency on JAXB. Regarding your first error, are you sure that all dependencies are being deployed with the application? It seems that the jakarta/xml/bind JAR was not found on the classpath.

AndresN17 commented 2 years ago

Hi Luis I'm using the last version 2.1.0 when I updated the pom.xml with the dependencies that are in the pom.xml in xades4j I got a different error that is in the second comment. I don't know why it's not recognized the dependencies that are in xades4j, maybe a thing with spring framework? I will look into it, but any ideas about the second error? The dependencies in my pom.xml :

<dependencies>
         <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-configuration-processor</artifactId>
           <optional>true</optional>
    </dependency>
    <dependency>
          <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
          <optional>true</optional>
    </dependency>
    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
    </dependency>
    <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
            <version>5.1.0</version>
        </dependency>
    <dependency>
         <groupId>com.googlecode.xades4j</groupId>
         <artifactId>xades4j</artifactId>
         <version>2.1.0</version>
    </dependency>
    <dependency>
            <groupId>org.apache.santuario</groupId>
            <artifactId>xmlsec</artifactId>
            <version>2.3.0</version>
        </dependency>
    <dependency>
         <groupId>org.bouncycastle</groupId>
         <artifactId>bcprov-jdk15on</artifactId>
         <version>1.70</version>
    </dependency>
    <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>3.0.2</version>
            <scope>runtime</scope>
        </dependency>
</dependencies>
luisgoncalves commented 2 years ago

Weird that you have to declare xades4j's dependencies in your pom. The second error seems to be the same thing, but with the dependencies of jakarta.xml.bind. It seems to depend on jakarta.activation, which is not being resolved, hence resulting in the "NoClassDefFoundError: jakarta/activation/DataSource" error.

You need to sort out the resolution of dependencies. Isn't there any issue with the way your packaging the application?

AndresN17 commented 2 years ago

Hi Luis, it seems is a problem with spring initializr and how configures the project, I made a new project without spring initializr and it runs perfectly, a thing to take in mind if anyone use it.

AndresN17 commented 2 years ago

To add one more thing the problem it's with spring boot itself, when I added the dependencies the problem with jakarta/xml/bind shows again it's weird but I don't find the reason why. The Parent:

         <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

The Dependencies:

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
AndresN17 commented 2 years ago

Sorry if I do practically spam but I found the solution haha, I just took out the Parent node and add the version to the dependencies and that makes it, like this:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.7.2</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <version>2.7.2</version>
    </dependency>

but now I have a different question, its the same issue https://github.com/luisgoncalves/xades4j/issues/259 , it looks that it's from my country, I go to that issue to continue?

luisgoncalves commented 2 years ago

Yes, better to keep the discussion where related

M4NN3 commented 2 years ago

Same problem here java.lang.NoClassDefFoundError: jakarta/xml/bind/JAXBException occurring in new XadesBesSigningProfile(kdp).newSigner(); using Spring Boot 2.7.3 and Java 1.8 How to solve it?

luisgoncalves commented 2 years ago

As said before:

are you sure that all dependencies are being deployed with the application? It seems that the jakarta/xml/bind JAR was not found on the classpath.

Also, beware that the xades4j 2.X.X requires Java 11.

M4NN3 commented 2 years ago

I could finally deploy it well by adding the next dependencies.

<dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.4.0-b180830.0359</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>jakarta.activation</groupId>
            <artifactId>jakarta.activation-api</artifactId>
            <version>2.0.1</version>
        </dependency>

Also, beware that the xades4j 2.X.X requires Java 11.

There was no need to upgrade to Java 11. Thanks.