ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Google Calendar API 삽질 일기
    개발 2008. 12. 5. 01:52

    요즘 구글 캘린더 API를 �

    간단하게 일정을 등록하고 수정하고 삭제하는 기능을 구현하려고 하는데, 언어장벽에서부터 쉽지가 않네요.

     

    구글에서는 구글 캐린더를 쉽게 사용할 수 있도록 api를 제공하고 있는데, 이를 더욱더 이용하기 쉽도록 자바로 라이브러리를 만들어 놓은 것도 있습니다.

    이 라이브러리를 이용해서 작업을 하고 있는데 한 가지 막히는 부분이 있었습니다.

     

    일정을 등록하고 수정하는 것은 api 대로 하면 되었지만 삭제만은 자꾸 오류가 나는 것이었죠.

    시키대로 했는데 말이죠.

     

     

    Deleting events

    To delete an existing item, use the following code:

    URL deleteUrl = new URL(updatedEntry.getEditLink().getHref());
    myService.delete(deleteUrl);

    The URL to use for deletion is the same as the edit URL, so this example is very similar to the previous one, except of course that we’re calling the delete method instead of update.

    The above code is roughly equivalent to sending DELETE http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID to the service.

     

     

    메뉴얼에는 위에처럼 간단하게 나와있습니다.

    하지만 정작 실행을 시키면 다음과 같은 오류가 나옵니다.

     

    2008. 12. 5 오전 1:30:40 dantes.gcalendar.MainFrame$8 actionPerformed
    심각: null
    com.google.gdata.util.ServiceForbiddenException: Forbidden
    If-Match or If-None-Match header required

            at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:505)
            at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:555)
            at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:480)
            at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:459)
            at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:527)
            at com.google.gdata.client.Service.delete(Service.java:1501)
            at com.google.gdata.client.GoogleService.delete(GoogleService.java:652)
            at com.google.gdata.client.Service.delete(Service.java:1463)
            at com.google.gdata.client.GoogleService.delete(GoogleService.java:637)
     

     

    Forbidden ....

    허용하지 않는 다는 뜻 같습니다.

    그리고 헤더에 뭔가가 필요하다고 요구하는 것 같습니다. (If-Match or If-None-Match header required)

     

    저게 무슨 뜻일까요?

     

    자바 라이브러리는 사용하기 쉽도록 많들어 놓은 것이기때문에 실제 api 에는 어떤 내용이 있는지 찾아보기로 했습니다.

     

    Deleting events

    To delete an event, first you retrieve the event you want to delete, then you send a DELETE request to the event’s edit URL. This is the same URL used to update the event.

    If you want to make sure that you don’t delete an event that has been changed by another client since you retrieved it, include an HTTP If-Match header that contains the original event’s ETag value. You can determine the original event’s ETag value by examining the <event> element’s gd:etag attribute.

    If you want to delete the event regardless of whether someone else has updated it since you retrieved it, then use If-Match: * and don’t include the ETag. (In this case, you don’t need to retrieve the event before deleting it.)

    For more information about ETags, see the Data API APIs reference guide.

     

     

    낮익은 단어가 보입니다. 바로  If-Match !!

    삭제나 수정을 위해서는 ETag를 포함하는 If-Match 를 헤더에 넣어야 한다고 하는 것 같습니다.

    그렇다면 또 ETag는 뭘까요?

     

    자료를 다시 찾아봅니다.ㅡㅡ;

     

     

    한 번 웹을 요청하면 css 파일이나 혹은 js 파일을 한번 다운로드하고 두번 다시 호출하지 않는다고 합니다.

    속도 개선을 위한 일종의 캐싱같은 개념이죠.

    이를 갱신하기 위해서는 다시 웹을 요청했을 때 최근 마지막으로 변경된 시간과 이 ETag의 값을 비교한다고 합니다.

     

    뭔지는 잘 모르겠지만, 이 ETag 란 놈은 일종의 버전관리 같은 녀석 같습니다.

     

    그래서 ETag관련 메소드가 있는지 살펴봤습니다.

    그랬더니 오~~~ 과연 BaseEntry .setETag() 라는 녀석이 있었습니다.

     

    그래서 다시 setETag() 라는 녀석을 찾아보니 이렇게 되어 있더군요.

     

     

    setEtag

    public void setEtag(java.lang.String v)
    Description copied from interface: IEntry
    Sets the value of the gd:etag attribute for this entry.

     

    Specified by:
    setEtag in interface IEntry

     

    ㅡㅡ;

    무언가를 넣으라는데.... 무엇을 넣으란 말입니까???

     

    잠시 좌절을 하다가 다시 메뉴얼을 자세히 봅니다.

    .....

    ....

    ...

    ..

    .

     

    위의 자바 라이브러리에서 이벤트 삭제를 위해 제공했던 두 줄.

    그 두 줄...

     

    URL deleteUrl = new URL(updatedEntry.getEditLink().getHref());
    myService.delete(deleteUrl);

     

    저 delete() 라는 메소드는 어떻게 생겼기게 이벤트 삭제가 가능할까?

    그래서 소스코드를 직접 다운받아 저 메소드를 살펴보기로 했습니다.

     

     

       /**
       * Deletes an existing entry (and associated media content, if any) using the
       * specified edit URL.
       *
       * @param resourceUrl the edit or medit edit url associated with the resource.
       * @throws IOException error communicating with the GData service.
       * @throws com.google.gdata.util.ResourceNotFoundException invalid entry URL.
       * @throws ServiceException delete request failed due to system error.
       */
      public void delete(URL resourceUrl) throws IOException, ServiceException {
        delete(resourceUrl, null);
      }

     

      /**
       * Deletes an existing entry (and associated media content, if any) using the
       * specified edit URL. This delete is conditional upon the provided tag
       * matching the current entity tag for the entry. If (and only if) they match,
       * the deletion will be performed.
       *
       * @param resourceUrl the edit or medit edit url associated with the resource.
       * @param etag the entity tag value that is the expected value for the target
       *        resource.   A value of {@code null} will not set an etag
       *        precondition and a value of <code>"*"</code> will perform an
       *        unconditional delete.
       * @throws IOException error communicating with the GData service.
       * @throws com.google.gdata.util.ResourceNotFoundException invalid entry URL.
       * @throws ServiceException delete request failed due to system error.
       */
      public void delete(URL resourceUrl, String etag)
          throws IOException, ServiceException {

        try {
          startVersionScope();
          GDataRequest request = createDeleteRequest(resourceUrl);
          request.setEtag(etag);
          request.execute();
        } finally {
          endVersionScope();
        }
      }

     

     

    delete()는 URL 객체를 인수로 받는군요.

    앗! 그런데 메소드가 오버로딩되어 있군요.

    그런데... 인수가... url 과 etag..

    ?

     

    etag?

     

    만약 인수가 하나만 들어가게 되면 etag는 null로 인식하게 되어 있네요.

     

     

    분명 컴파일 시에는 etag 관련된 값을 넣으라고 했고,

    메뉴얼에는 url 인수 하나만 넣게 되어 있었습니다.

    그렇다면 당연히 오류가 날 수 밖에 없는 상황이었군요.

    메뉴얼 대로 했다면 당연히 동작하지 않습니다. ㅡ.ㅡ;

     

    그래서 이번에 이벤트 삭제 메소드에 ETag 인수를 두었습니다.

     

    public void remove(CalendarEventEntry entry) throws MalformedURLException, IOException, ServiceException
        {
            URL deleteUrl = new URL(entry.getEditLink().getHref());
            myService.delete(deleteUrl, entry.getEtag());
        }

     

    오~~ 역시 잘되네요.

     

    삭제 메소드는 아래와 같이 두가지 인수를 두어야 합니다.

     

            myService.delete(deleteUrl, entry.getEtag());
     

    여기까지가 제가 며칠동안 api 삽질해가며 얻은 자료입니다.

     

    하지만 더욱 놀라운 것은 이게 아닙니다.

    자바 라이브러리를 다운로드 받으면 함께 제공되는 샘플이 있는데 거기에도 이와 같은 예제가 있더군요. 조금 다르긴 하지만....

     

     

    그렇다면 나는 진정으로 삽질을 한 것일까요???? 

    반응형

    '개발' 카테고리의 다른 글

    PHP 에서 파일다운로드 하기  (0) 2009.02.07
    Trac 설치  (0) 2009.02.05
    SwingWorker 클래스  (0) 2008.11.20
    넷빈 6.1에서 struts2 설치하기  (0) 2008.11.04
    사이트 글자 크기 제어하기  (0) 2008.10.31

    댓글

Designed by Tistory.