2011-11-30 26 views
5

Tôi đang làm việc trên một ứng dụng Java lớn có sử dụng Wicket 1.5 cùng với Hibernate/JPA 2. Wicket có quy tắc tiêu chuẩn rằng các đối tượng được lưu trữ trong phiên phải thực hiện Serializable. Chúng tôi có một quy tắc bổ sung là các đối tượng được quản lý JPA không được lưu trữ trong phiên. Thay vào đó, các đối tượng được quản lý JPA được nạp vào mỗi yêu cầu thông qua các mô hình có thể tháo rời.Mở rộng kiểm tra serialization của Wicket

Để làm phức tạp vấn đề, nó là hợp pháp để lưu trữ một đối tượng Entity trong phiên với điều kiện là nó chưa được tồn được nêu ra. Do đó, một số lớp học của chúng tôi đã triển khai Serializable.

Nếu tôi muốn mở rộng thử nghiệm serialization Wicket để phát hiện đối tượng thuộc sở hữu của JPA, làm thế nào tôi sẽ đi về nó? Điều này có thể xảy ra nếu không có một cái nĩa địa phương của Wicket?

Trả lời

5

Tại $ dayjob tôi, chúng tôi sử dụng cái gì những gì bạn mô tả, và những gì tôi có presented at several meetups (xem trượt 23 và trên). Bạn không cần phải nêm Wicket cho điều đó.

Về cơ bản những gì bạn làm là sao chép mã kiểm tra serializer và sửa đổi nó để bao gồm kiểm tra của bạn cũng như kiểm tra các lỗi serialization. Sau đó, trong giai đoạn cuối của chu kỳ yêu cầu bạn chạy trình kiểm tra bộ nối tiếp của riêng bạn trên các trang bị ảnh hưởng.

Vui lòng cung chúng tôi tạo ra kiểm tra cho lớp cơ sở chung của chúng ta, và thời tiết hay không thực thể có ben vẫn kiên trì. Nếu vậy, chúng tôi sẽ không yêu cầu. Ngoài ra chúng tôi có một cuộc gọi lại Ajax trong trang cơ sở của chúng tôi để kiểm tra thuộc tính phiên để xem có lỗi tuần tự hóa hay không. Nếu vậy, chúng tôi chuyển hướng đến trang lỗi với sự thất bại serialization, để đảm bảo rằng các nhà phát triển không bỏ qua các thực thể trong hệ thống phân cấp trang.

Dưới đây là thịt của kiểm tra của chúng tôi (các phương pháp check viết lại từ séc serializer Wicket của):

private void check(Object obj) 
{ 
    if (obj == null || obj.getClass().isAnnotationPresent(Deprecated.class) 
     || obj.getClass().isAnnotationPresent(SkipClass.class)) 
    { 
     return; 
    } 

    Class<?> cls = obj.getClass(); 
    nameStack.add(simpleName); 
    traceStack.add(new TraceSlot(obj, fieldDescription)); 

    if (!(obj instanceof Serializable) && (!Proxy.isProxyClass(cls))) 
    { 
     throw new WicketNotSerializableException(toPrettyPrintedStack(obj.getClass().getName()) 
      .toString(), exception); 
    } 
    if (obj instanceof IdObject) 
    { 
     Serializable id = ((IdObject) obj).getIdAsSerializable(); 
     if (id != null && !(id instanceof Long && ((Long) id) <= 0)) 
     { 
      throw new WicketContainsEntityException(toPrettyPrintedStack(
       obj.getClass().getName()).toString(), exception); 
     } 
    } 
    if (obj instanceof LoadableDetachableModel) 
    { 
     LoadableDetachableModel<?> ldm = (LoadableDetachableModel<?>) obj; 
     if (ldm.isAttached()) 
     { 
      throw new WicketContainsAttachedLDMException(toPrettyPrintedStack(
       obj.getClass().getName()).toString(), exception); 
     } 
    } 

Đối với Wicket 1.5 chúng tôi tạo riêng của chúng tôi PageStoreManager mà thực hiện những kiểm tra (và rất nhiều thứ khác, như cho phép lịch sử duyệt web phía máy chủ cho người dùng của chúng tôi). Chúng tôi cung cấp riêng RequestAdapter của chúng tôi bằng cách ghi đè PageStoreManager#newRequestAdapter(IPageManagerContext context) và làm việc kiểm tra tuần tự trong bộ chuyển đổi:

class DetachCheckingRequestAdapter extends RequestAdapter 
{ 
    public DetachCheckingRequestAdapter(IPageManagerContext context) 
    { 
     super(context); 
    } 

    @Override 
    protected void storeTouchedPages(List<IManageablePage> touchedPages) 
    { 
     super.storeTouchedPages(touchedPages); 
     if (Application.get().usesDevelopmentConfig()) 
     { 
      for (IManageablePage curPage : touchedPages) 
      { 
       if (!((Page) curPage).isErrorPage()) 
        testDetachedObjects(curPage); 
      } 
     } 
    } 

    private void testDetachedObjects(final IManageablePage page) 
    { 
     try 
     { 
      NotSerializableException exception = new NotSerializableException(); 
      EntityAndSerializableChecker checker = new EntityAndSerializableChecker(exception); 
      checker.writeObject(page); 
     } 
     catch (Exception ex) 
     { 
      log.error("Couldn't test/serialize the Page: " + page + ", error: " + ex); 
      Session.get().setDetachException(ex); 
     } 
    } 
} 
+0

Tôi đã thực hiện điều này trong ứng dụng của tôi, và nó hoạt động như một nét duyên dáng. Nó sẽ là một chút neater nếu Wicket có một điểm tập tin đính kèm thuận tiện cho kiểm tra phiên, nhưng điều này là khá duy trì. Cảm ơn. –

+1

Bạn được chào đón. Bạn được tự do gửi yêu cầu tính năng. Thật không may, chúng tôi không thể thực hiện việc kiểm tra chung này, nhưng việc có thể mở rộng khung công tác theo cách rõ ràng hơn sẽ tốt hơn. –

0

Một cách tiếp cận rất dễ dàng được tùy biến serialization của tổ chức của bạn:

public Object writeReplace() throws ObjectStreamException { 
    if (!isTransient()) { 
    throw new NotSerializableException("persistent objects must not be serialized"); 
    } 
    return this; 
} 

Chúng tôi đã đặt đoạn mã này vào tất cả các thực thể của chúng ta (tốt, thực sự là một lớp cơ sở chung được gọi là AbstractPersistentObject) và nó hoạt động khá tốt. Điều duy nhất nó phức tạp là chỉnh sửa các thực thể bền vững hoặc các thực thể tạm thời với các thuộc tính liên tục: bạn không được phép sắp xếp các đối tượng bẩn/chỉnh sửa/sửa đổi.

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