2012-09-20 32 views
11

Tôi gặp vấn đề với cách JAXB tạo ra các lớp bị ràng buộc cho một lược đồ XML (mà vì lợi ích của độ chính xác, tôi không thể sửa đổi). Tôi muốn ánh xạ một xsd: type ngày đến một đối tượng LOCALDATE Joda thời gian và, đọc here, herehere, tôi đã tạo ra DateAdapter lớp sau:JAXB, Ràng buộc tùy chỉnh, Adapter1.class và Joda-time

public class DateAdapter extends XmlAdapter<String,LocalDate> { 
    private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd"); 

    public LocalDate unmarshal(String v) throws Exception { 
     return fmt.parseLocalDate(v); 
    } 

    public String marshal(LocalDate v) throws Exception { 
     return v.toString("yyyyMMdd"); 
    } 
} 

Và tôi đã thêm dòng sau vào file ràng buộc toàn cầu của tôi :

<jaxb:globalBindings> 
     <jaxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date" 
      parseMethod="my.classes.adapters.DateAdapter.unmarshal" 
      printMethod="my.classes.adapters.DateAdapter.marshal" /> 
    </jaxb:globalBindings> 

vấn đề là, khi tôi cố gắng maven biên dịch dự án của tôi, nó không thành công với các lỗi sau:

[ERROR] \My\Path\MyProject\target\generated-sources\xjc\my\classes\generated\Adapter1.java:[20,59] non-static method unmarshal(java.lang.String) cannot be referenced from a static context 
[ERROR] \My\Path\MyProject\target\generated-sources\xjc\my\classes\generated\Adapter1.java:[24,59] non-static method marshal(org.joda.time.LocalDate) cannot be referenced from a static context 

... và đây là nơi mọi thứ trở nên kỳ lạ. JAXB tạo Lớp Adapter1 chứa các mục sau:

public class Adapter1 
    extends XmlAdapter<String, LocalDate> 
{ 


    public LocalDate unmarshal(String value) { 
     return (my.classes.adapters.DateAdapter.unmarshal(value)); 
    } 

    public String marshal(LocalDate value) { 
     return (my.classes.adapters.DateAdapter.marshal(value)); 
    } 

} 

.... đó là nguồn gốc của lỗi biên dịch.

Bây giờ, câu hỏi của tôi là:

  • được rằng bộ chuyển đổi của tôi là trọng XmlAdapter, tôi không thể làm cho phương pháp tĩnh .... làm thế nào để tránh tình trạng này?
  • Tôi có thể tránh việc tạo ra Adapter1.class hoàn toàn không ?? Có thể sử dụng chú thích cấp gói XmlJavaTypeAdapters và nếu có, làm thế nào để tôi thực hiện chính xác? (JAXB tạo ra một gói-info.java của riêng nó ....)

Hy vọng tôi đã làm rõ tình hình của tôi.
Cảm ơn

Trả lời

7

Bạn không cần phải mở rộng XmlAdapter.

Chỉ cần tạo phương thức tĩnh trên POJO và nó sẽ hoạt động.

Ví dụ:

public class DateAdapter { 
    private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd"); 

    public static LocalDate unmarshal(String v) throws Exception { 
     return fmt.parseLocalDate(v); 
    } 

    public static String marshal(LocalDate v) throws Exception { 
     return v.toString("yyyyMMdd"); 
    } 
} 
3

Khi tạo XmlAdapters từ lược đồ XML, bạn cần đặt logic cho chuyển đổi theo phương thức tĩnh không trong XmlAdapter. Đây là một XmlAdapter thúc đẩy logic đó có thể được tạo ra. Tôi nhận ra rằng đây là một cơ chế kỳ quặc.

Hoàn Ví dụ

3

Bạn đang mở rộng XmlAdapter được sử dụng khi bạn muốn chú thích mô hình Java của bạn cho JAXB, đó là thông qua các chú thích @XmlJavaTypeAdapter(Adapter1.class). Đối với trường hợp của bạn, bạn chỉ cần một lớp học với các phương pháp tĩnh mà không mở rộng XmlAdapter. Bạn sẽ cần phương thức phân tích (lấy một chuỗi và ngày trả về) và phương thức in (lấy một ngày và trả về một chuỗi) và đó là về nó.

3

tôi tìm thấy giải pháp này là hữu ích http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html

Bạn sẽ tạo ra một bộ chuyển đổi

package blog.jodatime; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 
import org.joda.time.DateTime; 

public class DateTimeAdapter 
    extends XmlAdapter<String, DateTime>{ 

    public DateTime unmarshal(String v) throws Exception { 
     //return new DateTime(v); - old solution that didn't properly handled the timezone 
     return DateTime.parse(v); 
    } 

    public String marshal(DateTime v) throws Exception { 
     return v.toString(); 
    } 

} 

Sau đó đăng ký nó với các chú thích bằng cách định nghĩa một blog/jodatime/package-info.java trong nguồn của bạn

@XmlJavaTypeAdapters({ @XmlJavaTypeAdapter(type = DateTime.class, value = JodaDateTimeJaxbAdapter.class) }) 
package blog.jodatime; 

import javax.xml.bind.annotation.adapters.*; 

import org.joda.time.*; 

Sau đó, bạn nên mong đợi rằng việc tuần tự hóa DateTime được thực hiện mà không có bất kỳ thay đổi nào khác, chỉ cần đừng quên chú thích lớp của bạn bằng @XmlRootElement.

+1

gì nếu tôi tạo ra 'lớp JAXB' tôi với 'xjc'? Chú thích của tôi sẽ bị ghi đè. –

17

Tôi đã ở trong ngữ cảnh đầu tiên của WSDL: không có java chút nào, chỉ cần tạo một ứng dụng khách CXF từ WSDL được cung cấp.

Tôi đã bị kẹt với sự xấu xí Adapter1.java trong một thời gian dài, nhưng tôi đã tìm thấy giải pháp there.

Bạn sẽ sử dụng XMLAdapter tùy chỉnh như đã được giải thích.

Mấu chốt của vấn đề này đã được bổ sung thêm phần mở rộng xjc đến tập tin ràng buộc toàn cầu:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.1"> 
    <jaxb:globalBindings> 
     <xjc:javaType adapter="com.xxx.tools.xjc.DateAdapter" 
     name="java.util.Date" xmlType="xs:dateTime" /> 
    </jaxb:globalBindings> 
</jaxb:bindings> 

XJC phần mở rộng cho phép việc sử dụng xjc:javaType chấp nhận bộ chuyển đổi tham số. Không yêu cầu phương pháp tĩnh nữa!

Lưu ý điều này dường như chỉ hoạt động với jaxb 2.1+.

1

Ví dụ hoàn chỉnh. Đây là bindings.xml của bạn:

<jaxws:bindings wsdlLocation="YourWsdl" 
     xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:jxb="http://java.sun.com/xml/ns/jaxb" 
     xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
     jxb:extensionBindingPrefixes="xjc"> 
    <jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='YourTargetNameSpace']"> 
     <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
      <xjc:javaType adapter="com.xxx.your.package.DateAdapter" name="java.util.Date" xmlType="xs:dateTime" /> 
     </jxb:globalBindings> 
    </jaxws:bindings> 
</jaxws:bindings> 

cộng với lớp Java:

package com.yourpackage; 

import java.util.Calendar; 
import java.util.Date; 
import java.util.GregorianCalendar; 

import javax.xml.bind.DatatypeConverter; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class DateAdapter extends XmlAdapter<String, Date> 
{ 

    @Override 
    public Date unmarshal(final String date) { 
     return DatatypeConverter.parseDate(date).getTime(); 
    } 

    @Override 
    public String marshal(final Date date) 
    { 
     Calendar calendar = new GregorianCalendar(); 
     calendar.setTime(date); 
     return DatatypeConverter.printDate(calendar); 
    } 

} 

cộng với nét pom.xml:

<plugin> 
    <groupId>org.apache.cxf</groupId> 
    <artifactId>cxf-codegen-plugin</artifactId> 
    <version>${cxf.version}</version> 
    <dependencies> 
     <dependency> 
      <groupId>org.jvnet.jaxb2_commons</groupId> 
      <artifactId>jaxb2-basics</artifactId> 
      <version>0.6.4</version> 
     </dependency> 
    </dependencies> 
    <executions> 
     <execution> 
      <id>generate-sources</id> 
      <phase>generate-sources</phase> 
      <configuration> 
       <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot> 
       <defaultOptions> 
        <autoNameResolution>true</autoNameResolution> 
       </defaultOptions> 
       <wsdlOptions> 
        <wsdlOption> 
         <wsdl>${basedir}/src/main/resources/your.wsdl</wsdl> 
         <extraargs> 
          <extraarg>-verbose</extraarg> 
          <extraargs>-xjc-npa</extraargs> 
          <extraarg>-xjc-Xsetters</extraarg> 
         </extraargs> 
         <bindingFiles> 
         <bindingFile>${basedir}/src/main/resources/binding.xml</bindingFile> 
         </bindingFiles> 
        </wsdlOption> 
       </wsdlOptions> 
      </configuration> 
      <goals> 
       <goal>wsdl2java</goal> 
      </goals> 
     </execution> 
    </executions> 
</plugin> 
0

Bạn không cần phải mở rộng XmlAdapter và với Joda -Thời gian v2, bạn thậm chí không cần phải thực hiện các phương pháp tĩnh, vì chúng đã được cung cấp.

<jaxb:javaType xmlns="http://java.sun.com/xml/ns/jaxb" 
    name="org.joda.time.LocalDate" 
    xmlType="xs:date" 
    parseMethod="org.joda.time.LocalDate.parse" 
    printMethod="java.lang.String.valueOf" 
/> 

Xem JAXB datatype converters for xs:date xs:time and xs:dateTime

Các vấn đề liên quan