2010-05-04 12 views
5

Giả sử tôi có lược đồ mô tả lớp phần tử gốc Root có chứa List<Entry> trong đó lớp Entry có tên trường bắt buộc.Tùy chỉnh xử lý lỗi của quy trình unmarshall JAXB

Sau đây là cách có vẻ trong mã:

@XmlRootElement 
class Root{ 
    @XmlElement(name="entry") 
    public List<Entry> entries = Lists.newArrayList(); 
} 

@XmlRootElement 
class Entry{ 
    @XmlElement(name="name",required=true) 
    public String name; 
} 

Nếu tôi cung cấp các XML sau cho unmarshalling:

<root> 
    <entry> 
    <name>ekeren</name> 
    </entry> 
    <entry> 
    </entry> 
</root> 

Tôi có một vấn đề vì sự xâm nhập thứ hai không chứa một tên. Vì vậy, unmarshall sản xuất null.

Có cách nào để tùy chỉnh JAXB để không đối chiếu một đối tượng Root chỉ chứa mục nhập "tốt" không?

Trả lời

5

Bạn có thể thêm magic afterUnmarshal method để chăm sóc mục rỗng:

@XmlRootElement 
class Root{ 
    @XmlElement(name="entry") 
    public List<Entry> entries = Lists.newArrayList(); 

    void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) { 
    Iterator<Entry> iter = entries.iterator(); 
    while (iter.hasNext()) { 
     if (iter.next().name == null) iter.remove(); 
    } 
    } 
} 

EDIT:

Không chắc nếu điều này là phù hợp hơn cho bạn, nhưng có lẽ đó là sự giúp đỡ. Bạn cũng có thể sử dụng Pacher, ví dụ: nếu không phải tất cả các đối tượng bạn cần phải sửa/xác nhận kết quả của bạn đều có sẵn trong afterUnmarshal (..)

10 Chạy bởi UnmarshallingTiếp theo sau khi thực hiện phân tích xong. Chủ yếu được sử dụng để giải quyết IDREF chuyển tiếp, nhưng nó có thể chạy bất kỳ hành động nào. (Javadoc)

Dưới đây là một ví dụ:

@XmlRootElement 
class Entry{ 
    @XmlElement(name="name",required=true) 
    public String name; 

    private boolean isValidEntry() { 
    return name != null; 
    } 

    void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) { 
    if (!isValidEntry()) { 
     // entry not yet added to parent - use a patcher 
     UnmarshallingContext.getInstance().addPatcher(new Patcher() { 
     public void run() throws SAXException { 
      ((Root)parent).removeEntry(this); 
     } 
     }); 
    } 
    } 
} 

tôi sẽ không lạm dụng nó quá nhiều tuy nhiên, không chỉ vì nó là Sun-chỉ API.

Nhưng nếu bạn đang thực sự xem xét một thứ có thể định cấu hình không phải là một phần của mã của chính các đối tượng được khắc phục. Nó có thể là tốt nhất để nhìn vào một cái gì đó sau khi unmarshalling. Tôi tự hỏi nếu Bean Validation (JSR 303) sẽ không phù hợp với bạn, ví dụ: sử dụng Hibernate Validator (không bị đe dọa bởi tên, bạn không cần Hibernate ORM để sử dụng nó). Tôi đã không sử dụng nó bản thân mình, nhưng bằng cách sử dụng một (mới) tiêu chuẩn cho xác nhận hợp lý âm thanh, phải không?

+0

đó là một ý tưởng hay, Cảm ơn. Tất nhiên tôi sẽ cần phải thiết lập eventHandler để khoan dung cho lỗi "trường được yêu cầu" nhưng nó không phải là một vấn đề. Tôi tự hỏi nếu có một giải pháp khác, tôi đang cố gắng để làm cho người dùng của hệ thống của tôi (tôi đang viết một lib cho nhóm của tôi mà đối phó với cấu hình) để có thể dễ dàng thiết lập tính năng này. Tôi có thể làm điều đó với chú thích và một số lớp introspection để xem tất cả các lĩnh vực cần phải được kiểm tra cho tên yêu cầu vấn đề ... bên trong afterUnmarshal (...). Tôi sẽ giữ điều này chưa được trả lời có thể có ai đó với một câu trả lời suiting hơn cho những gì tôi cần. – ekeren

+0

@ekeren xem bản chỉnh sửa của tôi, hy vọng điều đó sẽ hữu ích. cổ vũ – sfussenegger