顯示具有 Jersey 標籤的文章。 顯示所有文章
顯示具有 Jersey 標籤的文章。 顯示所有文章

URI names are case-sensitive when using Jersey

標題其實不很正確,嚴格來說是URI names are case-sensitive
不過我第一次寫RESTful Service是使用Miscrosoft的ASP .NET Web API,可能ASP .NET Web API內部有什麼機制處理過,case-sensitive這件事並沒有作用。

這陣子使用Java陣營的Jersey實作RESTful Service,發現無論是URL或request body都有分大小寫,例如

GET
http://localhost:8080/WebDemo1/rest/Group/1  成功, StatusCode:200
http://localhost:8080/WebDemo1/rest/group/1   失敗, StatusCode:404

POST
http://localhost:8080/WebDemo1/rest/Group/   成功, StatusCode:204
request body {"groupName":"MIS","parentID":1,"enable":"1","createCompany":"AAA","createName":"Karen"}
http://localhost:8080/WebDemo1/rest/Group/   失敗, StatusCode:500 找不到GroupName欄位
request body {"GroupName":"MIS","parentID":1,"enable":"1","createCompany":"AAA","createName":"Karen"}

本以為是Java區分大小寫的特性,想說找找有無IngoreCase之類的Func.可用,後來才發現錯怪Java了,其實是Jersey乖乖遵守W3C的標準(請參考6.2.2.1與 6.2.3)
所以透過Jersey開發RESTful Service要小心捏,但如果實在不想使用者因大小寫被擋住,可以考慮這篇文章@FormParam case sensitivity in Java Jersey的解法,或是棄用Jersey跳槽使用JBOSS開發的RESTEasy

參考文章
Case-insensitive URLs with JAX-RS

JSON responce for Jersey without @XmlRootElement

試Jersey的時候發現網路上的範例不外乎是這樣

●Entity:GroupData.java

@XmlRootElement
@Entity
public class GroupData { 

  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int GroupID;

  private String GroupName;

  @Temporal(TemporalType.TIMESTAMP)
  private Date CreateDate;

        //  getter & setter
public int getGroupID() {
return GroupID;
  }

  public String getGroupName() {
   return GroupName;
  }

  public void setGroupName(String groupName) {
   GroupName = groupName;
  }

  public Date getCreateDate() {
   return CreateDate;
  }

  public void setCreateDate(Date createDate) {
   CreateDate = createDate;
  }
}

●RESTful Service:GroupDataResource.java

@Path("/Group")
public class GroupDataResource {

  @GET
  @Path("{groupid}")
  @Produces(MediaType.APPLICATION_JSON )
  public GroupData getGroup(@PathParam("groupid") int groupID) {
  GroupData gData;
          //操作並取回資料gData,略...
   return gData;
  }
}

成果如下圖

一切都正常,但我不想每次Entity都透過XML來binding,但直接去掉@XmlRootElement又會拋錯,這邊有篇參考文章Configure Jersey/Jackson to NOT use @XmlElement field annotation for JSON field naming寫得不錯,但本人是Java新手XD  暫時先透過修改web.xml設定的方式來解決嚕,解決方式如下

1. 去掉@XmlRootElement
2. 在web.xml加入highlight處
< servlet>
< servlet-name>Jersey REST Service</ servlet-name>
< servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</ servlet-class>
< init-param>
< param-name>com.sun.jersey.config.property.packages</ param-name>
< param-value>com.quanta.WebDemo1</ param-value>
</ init-param>
< init-param>
    < param-name>com.sun.jersey.api.json.POJOMappingFeature</ param-name>
    < param-value>true</ param-value>
</ init-param>
< load-on-startup>1</ load-on-startup>
</ servlet>
< servlet-mapping>
< servlet-name>Jersey REST Service</ servlet-name>
< url-pattern>/rest/*</ url-pattern>
</ servlet-mapping>

解決後的成果

讚讚~也是JSON格式,但是Date type的資料怪怪的@@
下一篇來解決這個問題吧XD