2013-10-16 63 views
0

這是我的資源類:結果不會被髮送到瀏覽器

@Component 
@Path("forum/categories") 
@Produces(MediaType.APPLICATION_JSON) 
public class ForumCategoryResource { 

@Context 
UriInfo uriInfo; 

@Resource(name="forumService") 
private ForumService forumService; 

@GET 
@Path("tree/{rootId}") 
@Produces(MediaType.APPLICATION_JSON) 
public Response getCategoryTreeById(@PathParam("rootId") Integer rootId) { 

    System.out.println("Got request for tree by id: " + rootId); 

    Tree<ForumCategory> tree = forumService.getCategoryTreeById(rootId); 

    return Response.ok(new GenericEntity<Tree<ForumCategory>>(
      tree, tree.getClass() 
    )).build(); 
} 

這是我的數據類型,泛型類:

public class Tree<T> { 

    public interface Converter<T, S> { 
     S convert (T t); 
    } 

    public enum IterationStrategy { 
     PREORDER, 
     LEVELORDER, 
     POSTORDER 
    } 

    private T value; 
    private Tree<T> parent; 
    private List<Tree<T>> children; 
    private int height; 

    public Tree(Tree<T> tree) { 

     this.value = tree.value; 
     this.children = createListAdapterForHeightCalculation(tree.children); 
     this.parent = tree.parent; 
     this.height = tree.height; 
    } 

    public Tree(T value) { 
     this.value = value; 
     this.children = createListAdapterForHeightCalculation(Lists.<Tree<T>>newArrayList()); 
     this.height = 1; 
    } 

    public Tree<T> add(Tree<T> tree) { 
     children.add(tree); 
     tree.parent = this; 
     calculateHeightToRoot(tree); 
     return tree; 
    } 

    private ListAdapter<Tree<T>> createListAdapterForHeightCalculation(final List<Tree<T>> list) { 
     return new ListAdapter<Tree<T>>(list) { 

      @Override 
      public Tree<T> remove(int index) { 
       Tree<T> removedElement = super.remove(index);    
       int newMaxHeightAtThisLevel = getMaxHeight(list); 
       removedElement.parent.height = newMaxHeightAtThisLevel + 1; 
       calculateHeightToRoot(removedElement.parent); 
       return removedElement; 
      } 

      private int getMaxHeight(List<Tree<T>> children) { 

       int result = 0; 

       for (Tree<T> tree : children) { 
        result = Math.max(tree.height, result); 
       } 

       return result; 
      } 
     };  
    } 

    private void calculateHeight(Tree<T> parent, Tree<T> child) { 
     int height = Math.max(parent.height, child.height + 1); 
     parent.height = height; 
    } 

    private void calculateHeightToRoot(Tree<T> tree) { 

     Tree<T> parent = tree.parent; 
     Tree<T> child = tree; 


     while (! child.isRoot()) { 
      calculateHeight(parent, child); 
      parent = parent.parent; 
      child = child.parent; 
     } 
    } 

    public <S> Tree<S> convert(Converter<T, S> converter) { 

     Tree<S> result = new Tree<S>(converter.convert(this.value)); 

     for (Tree<T> child : this.children) { 
      result.add(child.convert(converter)); 
     } 

     return result; 
    } 

    public Tree<T> add(T value) { 
     return add(new Tree<T>(value)); 
    } 

    public int getHeight() { 
     return height; 
    } 

    public Tree<T> getParent() { 
     return parent; 
    } 

    public T getValue() { 
     return value; 
    } 

    public List<Tree<T>> getChildren() { 
     return children;   
    } 

    public boolean isRoot() { 
     return parent == null; 
    } 

    public boolean isLeaf() { 
     return children.isEmpty(); 
    } 

    public boolean hasParent() { 
     return ! isRoot(); 
    } 

    public boolean hasChildren() { 
     return ! isLeaf(); 
    } 

    @Override 
    public String toString() { 
     return toString(this, null); 
    } 

    private String toString(Tree<T> tree, String prefix) { 

     prefix = (prefix == null) ? "" : prefix; 

     StringBuilder result = new StringBuilder(prefix + ObjectUtils.toString(tree.value) + ":" + tree.height); 
     result.append("\n"); 

     for (Tree<T> child : tree.children) { 
      String newPrefix; 
      if (StringUtils.isEmpty(prefix)) { 
       newPrefix = "|- "; 
      } 
      else { 
       newPrefix = "| " + prefix; 
      } 
      result.append(toString(child, newPrefix)); 
     } 

     return result.toString(); 
    } 

    public List<T> getPathFromRoot() { 
     List<T> result = getPathToRoot(); 
     Collections.reverse(result); 
     return result; 
    } 

    public List<T> getPathToRoot() { 
     List<T> result = new ArrayList<T>(); 

     Tree<T> pathElement = this; 

     while (! pathElement.isRoot()) { 
      result.add(pathElement.value); 
      pathElement = pathElement.parent; 
     } 

     result.add(pathElement.value); 
     return result; 
    } 

    public boolean containsChildWithValue(T value) { 
     for (Tree<T> child : children) { 
      if (ObjectUtils.equals(value,child.getValue())) return true; 
     } 
     return false; 
    } 

    public Tree<T> findFirst(T value) { 
     return findFirst(value, IterationStrategy.PREORDER); 
    } 

    public Tree<T> findFirst(T value, IterationStrategy strategy) { 

     switch (strategy) { 

      case PREORDER: return findFirstPreOrder(this, value); 
      case LEVELORDER: return findFirstLevelOrder(Arrays.asList(this), value); 
      case POSTORDER: return findFirstPostOrder(this, value); 
     } 

     return null; 
    } 

    private Tree<T> findFirstLevelOrder(List<Tree<T>> treeList, T value) { 

     List<Tree<T>> treeListChildren = new ArrayList<Tree<T>>(); 

     for (Tree<T> tree : treeList) { 
      if (tree.value.equals(value)) { 
       return tree; 
      } 

      treeListChildren.addAll(tree.children); 
     } 

     if (treeListChildren.size() > 0) { 
      return findFirstLevelOrder(treeListChildren, value); 
     } 

     return null; 
    } 

    private Tree<T> findFirstPostOrder(Tree<T> tree, T value) { 

     for (Tree<T> child : tree.children) { 
      Tree<T> result = findFirstPostOrder(child, value); 
      if (result != null) { 
       return result; 
      } 
     } 

     if (tree.value.equals(value)) { 
      return tree; 
     } 

     return null; 
    } 

    private Tree<T> findFirstPreOrder(Tree<T> tree, T value) { 

     if (tree.value.equals(value)) { 
      return tree; 
     } 

     for (Tree<T> child : tree.children) { 
      Tree<T> result = findFirstPreOrder(child, value); 
      if (result != null) return result; 
     } 

     return null; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result 
       + ((children == null) ? 0 : children.hashCode()); 
     result = prime * result + height; 
     result = prime * result + ((value == null) ? 0 : value.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     @SuppressWarnings("unchecked") 
     Tree<T> other = (Tree<T>) obj; 
     if (children == null) { 
      if (other.children != null) 
       return false; 
     } else if (!children.equals(other.children)) 
      return false; 
     if (height != other.height) 
      return false; 
     if (value == null) { 
      if (other.value != null) 
       return false; 
     } else if (!value.equals(other.value)) 
      return false; 
     return true; 
    } 

} 

這是我的領域類:

public class ForumCategory { 

    private Integer forumCategoryId; 
    private String nameKey; 
    private String descriptionKey; 

    public ForumCategory() { 
    } 

    public ForumCategory(String nameKey, String descriptionKey) { 
     this.nameKey = nameKey; 
     this.descriptionKey = descriptionKey; 
    } 

    @Override 
    public int hashCode() { 
     return new HashCodeBuilder().append(forumCategoryId).toHashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 

     if (this == obj) { 
      return true; 
     } 

     if (obj == null) { 
      return false; 
     } 

     if (getClass() != obj.getClass()) { 
      return false; 
     } 

     ForumCategory other = (ForumCategory) obj; 
     return new EqualsBuilder().append(this.forumCategoryId, other.forumCategoryId).isEquals(); 
    } 

    public String getNameKey() { 
     return nameKey; 
    } 

    public void setNameKey(String nameKey) { 
     this.nameKey = nameKey; 
    } 

    public String getDescriptionKey() { 
     return descriptionKey; 
    } 

    public void setDescriptionKey(String descriptionKey) { 
     this.descriptionKey = descriptionKey; 
    } 

    public Integer getForumCategoryId() { 
     return forumCategoryId; 
    } 

    public void setForumCategoryId(Integer forumCategoryId) { 
     this.forumCategoryId = forumCategoryId; 
    } 

    @Override 
    public String toString() { 
     return "ForumCategory [forumCategoryId=" + forumCategoryId 
       + ", nameKey=" + nameKey + ", descriptionKey=" + descriptionKey 
       + "]"; 
    } 


} 

這是我的Tree類的MessageBodyWriter:

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
public class TreeWriter implements MessageBodyWriter<Tree<?>> { 

    private static final Tree<?> NULL_TREE = new Tree<Object>((Object)null); 
    private static final Charset CHARSET = Charset.forName("UTF-8"); 

    private ObjectMapper objectMapper = new ObjectMapper(); 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, 
      Annotation[] annotations, MediaType mediaType) { 

     System.out.println("isWritable"); 
     return type == NULL_TREE.getClass(); 
    } 

    @Override 
    public long getSize(Tree<?> tree, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     System.out.println("getSize"); 

     try { 
      return getTreeAsJsonString(tree).length() * Character.SIZE/Byte.SIZE; 
     } 
     catch (IOException e) { 
      throw new WebApplicationException(e); 
     } 
    } 

    @Override 
    public void writeTo(Tree<?> tree, Class<?> type, Type genericType, 
      Annotation[] annotations, MediaType mediaType, 
      MultivaluedMap<String, Object> httpHeaders, 
      OutputStream entityStream) throws IOException, 
      WebApplicationException { 

     System.out.println("writeTo"); 
     System.out.println(tree); 
     String jsonString = getTreeAsJsonString(tree); 
     System.out.println(jsonString); 
     entityStream.write(jsonString.getBytes(CHARSET)); 
     entityStream.flush(); 
    } 

    private String getTreeAsJsonString(Tree<?> tree) throws IOException { 

     if (tree != null) { 

      StringBuilder result = new StringBuilder(); 
      appendTree(result, tree); 
      return result.toString(); 
     } 

     return "null"; 
    } 

    private void appendTree(StringBuilder result, Tree<?> tree) throws IOException { 

     result.append("{");  
     appendTreeValue(result, tree); 
     result.append(","); 
     appendTreeChildren(result, tree); 
     result.append(","); 
     appendTreeHeight(result, tree); 
     result.append("}"); 

    } 

    private void appendTreeHeight(StringBuilder result, Tree<?> tree) { 
     result.append("\"height\":"); 
     result.append(tree.getHeight()); 
    } 

    private void appendTreeChildren(StringBuilder result, Tree<?> tree) throws IOException { 

     result.append("\"children\":["); 

     boolean hasChildren = false; 

     for (Tree<?> child : tree.getChildren()) { 
      appendTree(result, child); 
      result.append(","); 
      hasChildren = true; 
     } 

     if (hasChildren) { 
      result.deleteCharAt(result.length() - 1); 
     } 

     result.append("]"); 
    } 

    private void appendTreeValue(StringBuilder result, Tree<?> tree) throws IOException { 
     result.append("\"value\":"); 
     result.append(objectMapper.writeValueAsString(tree.getValue()));   
    } 
} 

而且我從代碼的System.out.println以下的輸出:

Got request for tree by id: 1 
isWritable 
getSize 
writeTo 
ForumCategory [forumCategoryId=1, nameKey=cat.name.a, descriptionKey=cat.desc.a]:2 
|- ForumCategory [forumCategoryId=2, nameKey=a, descriptionKey=b]:1 

{"value":{"forumCategoryId":1,"nameKey":"cat.name.a","descriptionKey":"cat.desc.a"},"children":[{"value":{"forumCategoryId":2,"nameKey":"a","descriptionKey":"b"},"children":[],"height":1}],"height":2} 

的問題是,沒有在我的瀏覽器中顯示。從一個普通的POJO接收json就像一個魅力。我遇到的唯一問題是從返回Tree <的休息服務獲取答案? >數據。

編輯:

我試着用郵差休息客戶端,並與下面的消息失敗:

響應狀態爲0 退房的W3C的XMLHttpRequest Level 2規範如需詳細瞭解當這個情況發生時。

W3C規範說:

狀態屬性必須返回運行這些步驟的結果:

如果狀態UNSENT或打開,返回0,並終止這些步驟。

如果設置了錯誤標誌,則返回0並終止這些步驟。

返回HTTP狀態碼。

+0

我得到的HTTP標頭: HTTP/1.1 200 OK 的Content-Length:400 內容類型:應用程序/ JSON 服務器:碼頭(6.1.10) –

回答

0

我想通了。

首先,我試圖從返回的getSize 0 ..

然後我可能通過使用string.length減算錯長度()* Character.SIZE/Byte.SIZE。

然後我試着從getSize返回-1,這讓jersey-json自己計算出長度。

相關問題