Reputation: 31
I'm struggling with migration from JAXB 2 to latest version. I'm using an XSD file and an XJB file which contains annotation for the root element. But if I try to compile it, it ends up with an error:
[ERROR] Failed to execute goal org.jvnet.jaxb:jaxb-maven-plugin:4.0.8:generate (schema-v2) on project org.myproject.exporter: Execution schema-v2 of goal org.jvnet.jaxb:jaxb-maven-plugin:4.0.8:generate failed: A required class was missing while executing org.jvnet.jaxb:jaxb-maven-plugin:4.0.8:generate: javax/xml/bind/JAXBException
[ERROR] -----------------------------------------------------
[ERROR] realm = plugin>org.jvnet.jaxb:jaxb-maven-plugin:4.0.8
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/C:/Users/myuser/.m2/repository/org/jvnet/jaxb/jaxb-maven-plugin/4.0.8/jaxb-maven-plugin-4.0.8.jar
[ERROR] urls[1] = file:/C:/Users/myuser/.m2/repository/jakarta/xml/bind/jakarta.xml.bind-api/4.0.2/jakarta.xml.bind-api-4.0.2.jar
... a bunch of similiar error lines ...
[ERROR] Number of foreign imports: 1
I don't want to use java.xml
(but jakarta.xml
instead), but I don't know where it is included. So, here is my XSD file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
targetNamespace="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
jaxb:version="3.0"
xmlns:annox="urn:jaxb.jvnet.org:annox"
jaxb:extensionBindingPrefixes="annox"
elementFormDefault="qualified">
<xs:import namespace="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" schemaLocation="FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_QualifiedDataType_100.xsd"/>
<xs:import namespace="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" schemaLocation="FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_ReusableAggregateBusinessInformationEntity_100.xsd"/>
<xs:import namespace="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" schemaLocation="FACTUR-X_EXTENDED_urn_un_unece_uncefact_data_standard_UnqualifiedDataType_100.xsd"/>
<!-- definition slightly changed so that xjb could annotate it with XmlRootelement -->
<xs:element name="CrossIndustryInvoice">
<xs:complexType>
<xs:sequence>
<xs:element name="ExchangedDocumentContext" type="ram:ExchangedDocumentContextType"/>
<xs:element name="ExchangedDocument" type="ram:ExchangedDocumentType"/>
<xs:element name="SupplyChainTradeTransaction" type="ram:SupplyChainTradeTransactionType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
and this is the XJB file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="urn:jaxb.jvnet.org:annox"
jaxb:extensionBindingPrefixes="annox"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jaxb https://jakarta.ee/xml/ns/jaxb/bindingschema_3_0.xsd"
version="3.0">
<jaxb:globalBindings typesafeEnumMaxMembers="900" enableJavaNamingConventions="true" underscoreBinding="asCharInWord" typesafeEnumMemberName="generateName">
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
parseMethod="jakarta.xml.bind.DatatypeConverter.parseDateTime"
printMethod="jakarta.xml.bind.DatatypeConverter.printDateTime" />
<!-- Force all classes implements Serializable -->
<jaxb:serializable uid="1" />
</jaxb:globalBindings>
<!-- Annotate the following classes with XmlRootElement -->
<jaxb:bindings schemaLocation="FACTUR-X_EXTENDED.xsd" node="/xs:schema">
<jaxb:schemaBindings><jaxb:package name="org.myproject.export.facturx.modelgen" /></jaxb:schemaBindings>
<jaxb:bindings node="xs:element[@name='CrossIndustryInvoice']">
<annox:annotate>
<annox:annotate annox:class="jakarta.xml.bind.annotation.XmlRootElement" name="CrossIndustryInvoiceType"/>
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
The pom file includes the following:
<!-- generate schema file for entities
generate JAXB classes for entities -->
<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-maven-plugin</artifactId>
<version>4.0.8</version>
<executions>
<execution>
<id>schema-v2</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<specVersion>3.0</specVersion>
<extension>true</extension>
<forceRegenerate>true</forceRegenerate>
<verbose>true</verbose>
<locale>en</locale>
<schemaDirectory>${basedir}/src/main/resources/schema-v2</schemaDirectory>
<!-- xjb doesn't work :-( -->
<bindingDirectory>src/main/resources/schema-v2</bindingDirectory>
<generateDirectory>src-gen/main/java</generateDirectory>
<encoding>${encoding}</encoding>
<generatePackage>org.myproject.export.facturx.modelgen</generatePackage>
<args>
<arg>-Xfluent-api</arg>
<arg>-Xannotate</arg>
<arg>-npa</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>${jaxb2.basics.version}</version>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-plugin-annotate</artifactId>
<version>${jaxb2.basics.version}</version>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>${jaxb2.basics.version}</version>
</plugin>
</plugins>
</configuration>
</execution>
</executions>
<configuration>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>1.11.1</version>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>2.0.14</version>
</plugin>
<plugin>
<groupId>net.java.dev.jaxb2-commons</groupId>
<artifactId>jaxb-fluent-api</artifactId>
<version>2.1.8</version>
</plugin>
</plugins>
</configuration>
<dependencies>
<!-- https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-default-value</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</plugin>
It seems that fluent-api
and annotate
aren't recognized anymore. With org.jvnet.jaxb2.maven2
v0.14.0 all things were generated successfully without any errors.
If you could give me a hint where I can start to fix it you're welcome :-) Thanks in advance,
Ralf
Upvotes: 0
Views: 73
Reputation: 476
You can use these dependencies to facilitate your migration from JAXB 2 to the latest version and to configure the Xannotate
and XfluentAPI
options. In fact, the provided demo (zip) uses these artifacts and options in its pom.xml
+- org.patrodyne.jvnet:hisrc-higherjaxb-maven-plugin:2.2.1
+- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.2:compile
+- org.glassfish.jaxb:jaxb-runtime:jar:4.0.5:runtime
| \- org.glassfish.jaxb:jaxb-core:jar:4.0.5:runtime
+- org.patrodyne.jvnet:hisrc-basicjaxb-runtime:jar:2.2.1:compile
+- org.patrodyne.jvnet:hisrc-basicjaxb-testing:jar:2.2.1:test
| +- org.junit.jupiter:junit-jupiter-api:jar:5.10.2:test
| \- org.glassfish.jaxb:jaxb-xjc:jar:4.0.5:test
\- org.slf4j:slf4j-simple:jar:2.0.12:runtime
The demo is a stand-alone Maven project. After downloading it and expanding the zip to your local path, you can run the test(s) and/or execute the application using:
mvn -Ptest clean test
mvn -Pexec compile exec:java
Here's an example of the OUTPUT.txt from running the unit test(s).
This project generates JAXB classes for the UN/CEFACT schemas publicly available at CII_D23B_0.zip and XMLSchemas-D23B.zip. The first ZIP is used to generate the JAXB classes and the second zip is scraped to provide additional CCTS names and descriptions.
Sample XML data is gratefully included from these GitHub repositories to implement unit testing for the generated schema:
Each of the sample data files provides an XML representation of a mock CrossIndustryInvoice
instance. The generated JAXB class for this element is annotated with @XmlRootElement
to support unmarshalling and marshaling in the unit tests and in the sample application.
Further, this demo includes examples of XJC plugins to add custom hashCode
, equals
, toString
and implementations to each generated JAXB class.
The demo includes the binding file shown below to add an @XmlRootElement
annotation to the Java class generated for the CrossIndustryInvoiceType
from the CrossIndustryInvoice_100pD23B.xsd in the urn:un:unece:uncefact namespace.
Binding file: uncefact1.xjb
<jaxb:bindings schemaLocation="uncefact/CII_D23B_0/100/CrossIndustryInvoice_100pD23B.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[@name='CrossIndustryInvoiceType']">
<!-- Annotate CrossIndustryInvoiceType with XmlRootElement -->
<annox:annotate>@jakarta.xml.bind.annotation.XmlRootElement(name="CrossIndustryInvoice")</annox:annotate>
<!-- Annotate namespace(s) with custom prefixes -->
...
</jaxb:bindings>
</jaxb:bindings>
The demo uses the XfleuntAPI
option to add method chaining to the generated classes. Here is an example of a unit test that fluently configures an instance of CrossIndustryInvoiceType
.
...
@Test
public void testMarshalSample() throws Exception
{
final String SAMPLE_CCI_FILENAME = "src/test/samples/01.01a-INVOICE_uncefact.xml";
// Unmarshal the sample for to assert expectations
Object sample = getValue(getUnmarshaller().unmarshal(new File(SAMPLE_CCI_FILENAME)));
assertInstanceOf(CrossIndustryInvoiceType.class, sample);
CrossIndustryInvoiceType cii1 = (CrossIndustryInvoiceType) sample;
// Create CrossIndustryInvoiceType and use ExchangedDocumentContextType
CrossIndustryInvoiceType cii2 = RSM.createCrossIndustryInvoiceType()
.useExchangedDocumentContext(RAM.createExchangedDocumentContextType()
.useTestIndicator(UDT.createIndicatorType()
.useIndicator(true))
.useGuidelineSpecifiedDocumentContextParameter(RAM.createDocumentContextParameterType()
.useID(UDT.createIDType()
.useValue("urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3")))
);
// CII: Use ExchangedDocument
cii2.useExchangedDocument(RAM.createExchangedDocumentType()
.useID(UDT.createIDType()
.useValue("123456XX"))
.useTypeCode(QDT.createDocumentCodeType()
.useValue(DocumentNameCodeContentType.COMMERCIAL_INVOICE))
.useIssueDateTime(UDT.createDateTimeType()
.useDateTimeString(UDT.createDateTimeDateTimeStringType()
.useFormat(DateOnlyFormatCodeContentType.CCYYMMDD.value())
.useValue("20160404")))
.useIncludedNote(RAM.createNoteType()
.useContent(UDT.createTextType()
.useValue("Es gelten unsere Allgem. Geschäftsbedingungen, die Sie unter […] finden."))
.useSubjectCode(UDT.createCodeType()
.useValue("ADU")
)
)
);
// CII: Use SupplyChainTradeTransaction
cii2.useSupplyChainTradeTransaction(RAM.createSupplyChainTradeTransactionType()
.useIncludedSupplyChainTradeLineItem(RAM.createSupplyChainTradeLineItemType()
.useAssociatedDocumentLineDocument(RAM.createDocumentLineDocumentType()
.useLineID(UDT.createIDType()
.useValue("Zeitschrift [...]"))
.useIncludedNote(RAM.createNoteType()
.useContent(UDT.createTextType()
.useValue("Die letzte Lieferung im Rahmen des abgerechneten Abonnements erfolgt in 12/2016 Lieferung erfolgt / erfolgte direkt vom Verlag"))))
.useSpecifiedTradeProduct(RAM.createTradeProductType()
.useSellerAssignedID(UDT.createIDType()
.useValue("246"))
.useName(UDT.createTextType()
.useValue("Zeitschrift [...]"))
.useDescription(UDT.createTextType()
.useValue("Zeitschrift Inland"))
.useDesignatedProductClassification(RAM.createProductClassificationType()
.useClassCode(UDT.createCodeType()
.useListID("IB")
.useValue("0721-880X"))))
.useSpecifiedLineTradeAgreement(RAM.createLineTradeAgreementType()
.useBuyerOrderReferencedDocument(RAM.createReferencedDocumentType()
.useLineID(UDT.createIDType()
.useValue("6171175.1")))
.useNetPriceProductTradePrice(RAM.createTradePriceType()
.useChargeAmount(UDT.createAmountType()
.useValue(new BigDecimal("288.79")))))
.useSpecifiedLineTradeDelivery(RAM.createLineTradeDeliveryType()
.useBilledQuantity(UDT.createQuantityType()
.useUnitCode("XPP")
.useValue(BigDecimal.ONE)))
.useSpecifiedLineTradeSettlement(RAM.createLineTradeSettlementType()
.useApplicableTradeTax(RAM.createTradeTaxType()
.useTypeCode(QDT.createTaxTypeCodeType()
.useValue(DutyTaxFeeTypeCodeContentType.VALUE_ADDED_TAX))
.useCategoryCode(QDT.createTaxCategoryCodeType()
.useValue(DutyorTaxorFeeCategoryCodeContentType.STANDARD_RATE))
.useRateApplicablePercent(UDT.createPercentType()
.useValue(new BigDecimal("7"))))
.useBillingSpecifiedPeriod(RAM.createSpecifiedPeriodType()
.useStartDateTime(UDT.createDateTimeType()
.useDateTimeString(UDT.createDateTimeDateTimeStringType()
.useFormat(DateOnlyFormatCodeContentType.CCYYMMDD.value())
.useValue("20160101")))
.useEndDateTime(UDT.createDateTimeType()
.useDateTimeString(UDT.createDateTimeDateTimeStringType()
.useFormat(DateOnlyFormatCodeContentType.CCYYMMDD.value())
.useValue("20161231"))))
.useSpecifiedTradeSettlementLineMonetarySummation(RAM.createTradeSettlementLineMonetarySummationType()
.useLineTotalAmount(UDT.createAmountType()
.useValue(new BigDecimal("288.79"))))))
.useIncludedSupplyChainTradeLineItem(RAM.createSupplyChainTradeLineItemType()
.useAssociatedDocumentLineDocument(RAM.createDocumentLineDocumentType()
.useLineID(UDT.createIDType()
.useValue("Porto + Versandkosten")))
.useSpecifiedTradeProduct(RAM.createTradeProductType()
.useName(UDT.createTextType()
.useValue("Porto + Versandkosten")))
.useSpecifiedLineTradeAgreement(RAM.createLineTradeAgreementType()
.useNetPriceProductTradePrice(RAM.createTradePriceType()
.useChargeAmount(UDT.createAmountType()
.useValue(new BigDecimal("26.07")))))
.useSpecifiedLineTradeDelivery(RAM.createLineTradeDeliveryType()
.useBilledQuantity(UDT.createQuantityType()
.useUnitCode("XPP")
.useValue(BigDecimal.ONE)))
.useSpecifiedLineTradeSettlement(RAM.createLineTradeSettlementType()
.useApplicableTradeTax(RAM.createTradeTaxType()
.useTypeCode(QDT.createTaxTypeCodeType()
.useValue(DutyTaxFeeTypeCodeContentType.VALUE_ADDED_TAX))
.useCategoryCode(QDT.createTaxCategoryCodeType()
.useValue(DutyorTaxorFeeCategoryCodeContentType.STANDARD_RATE))
.useRateApplicablePercent(UDT.createPercentType()
.useValue(new BigDecimal("7"))))
.useSpecifiedTradeSettlementLineMonetarySummation(RAM.createTradeSettlementLineMonetarySummationType()
.useLineTotalAmount(UDT.createAmountType()
.useValue(new BigDecimal("26.07"))))))
.useApplicableHeaderTradeAgreement(RAM.createHeaderTradeAgreementType()
.useBuyerReference(UDT.createTextType()
.useValue("04011000-12345-03"))
.useSellerTradeParty(RAM.createTradePartyType()
.useName(UDT.createTextType()
.useValue("[Seller name]"))
.useDescription(UDT.createTextType()
.useValue("123/456/7890, HRA-Eintrag in […]"))
.useSpecifiedLegalOrganization(RAM.createLegalOrganizationType()
.useID(UDT.createIDType()
.useValue("[HRA-Eintrag]"))
.useTradingBusinessName(UDT.createTextType()
.useValue("[Seller trading name]")))
.useDefinedTradeContact(RAM.createTradeContactType()
.usePersonName(UDT.createTextType()
.useValue("nicht vorhanden"))
.useTelephoneUniversalCommunication(RAM.createUniversalCommunicationType()
.useCompleteNumber(UDT.createTextType()
.useValue("+49 1234-5678")))
.useEmailURIUniversalCommunication(RAM.createUniversalCommunicationType()
.useURIID(UDT.createIDType()
.useValue("[email protected]"))))
.usePostalTradeAddress(RAM.createTradeAddressType()
.usePostcodeCode(UDT.createCodeType()
.useValue("12345"))
.useLineOne(UDT.createTextType()
.useValue("[Seller address line 1]"))
.useCityName(UDT.createTextType()
.useValue("[Seller city]"))
.useCountryID(QDT.createCountryIDType()
.useValue(ISOTwoletterCountryCodeContentType.DE)))
.useSpecifiedTaxRegistration(RAM.createTaxRegistrationType()
.useID(UDT.createIDType()
.useSchemeID(ReferenceTypeCodeContentType.VAT_REGISTRATION_NUMBER.value())
.useValue("DE 123456789"))))
.useBuyerTradeParty(RAM.createTradePartyType()
.useID(UDT.createIDType()
.useValue("[Buyer identifier]"))
.useName(UDT.createTextType()
.useValue("[Buyer name]"))
.usePostalTradeAddress(RAM.createTradeAddressType()
.usePostcodeCode(UDT.createCodeType()
.useValue("12345"))
.useLineOne(UDT.createTextType()
.useValue("[Buyer address line 1]"))
.useCityName(UDT.createTextType()
.useValue("[Buyer city]"))
.useCountryID(QDT.createCountryIDType()
.useValue(ISOTwoletterCountryCodeContentType.DE)))
)
)
.useApplicableHeaderTradeDelivery(RAM.createHeaderTradeDeliveryType())
.useApplicableHeaderTradeSettlement(RAM.createHeaderTradeSettlementType()
.useInvoiceCurrencyCode(QDT.createCurrencyCodeType()
.useValue(ISO3AlphaCurrencyCodeContentType.EUR))
.useSpecifiedTradeSettlementPaymentMeans(RAM.createTradeSettlementPaymentMeansType()
.useTypeCode(QDT.createPaymentMeansCodeType()
.useValue(PaymentMeansCodeContentType.SEPA_CREDIT_TRANSFER))
.usePayeePartyCreditorFinancialAccount(RAM.createCreditorFinancialAccountType()
.useIBANID(UDT.createIDType()
.useValue("DE75512108001245126199")))
)
.useApplicableTradeTax(RAM.createTradeTaxType()
.useCalculatedAmount(UDT.createAmountType()
.useValue(new BigDecimal("22.04")))
.useTypeCode(QDT.createTaxTypeCodeType()
.useValue(DutyTaxFeeTypeCodeContentType.VALUE_ADDED_TAX))
.useBasisAmount(UDT.createAmountType()
.useValue(new BigDecimal("314.86")))
.useCategoryCode(QDT.createTaxCategoryCodeType()
.useValue(DutyorTaxorFeeCategoryCodeContentType.STANDARD_RATE))
.useRateApplicablePercent(UDT.createPercentType()
.useValue(new BigDecimal("7"))))
.useSpecifiedTradePaymentTerms(RAM.createTradePaymentTermsType()
.useDescription(UDT.createTextType()
.useValue("Zahlbar sofort ohne Abzug.")))
.useSpecifiedTradeSettlementHeaderMonetarySummation(RAM.createTradeSettlementHeaderMonetarySummationType()
.useLineTotalAmount(UDT.createAmountType()
.useValue(new BigDecimal("314.86")))
.useTaxBasisTotalAmount(UDT.createAmountType()
.useValue(new BigDecimal("314.86")))
.useTaxTotalAmount(UDT.createAmountType()
.useCurrencyID(ISO3AlphaCurrencyCodeContentType.EUR.toString())
.useValue(new BigDecimal("22.04")))
.useGrandTotalAmount(UDT.createAmountType()
.useValue(new BigDecimal("336.9")))
.useDuePayableAmount(UDT.createAmountType()
.useValue(new BigDecimal("336.9")))
)
)
);
// Assert that the fluent construct matches the sample.
assertEquals(cii1, cii2, "Instance should match sample");
String xmlDoc = marshal(getMarshaller(), cii2);
getLogger().debug("Document:\n\n{}", xmlDoc);
}
...
Disclaimer: I am the maintainer for the HiSrc projects.
Upvotes: 0