Bookmark and Share

Flickr Samples

This sample contains the implementation of a some Flickr Rest APIs.

This example is more complex than the Google or Twitter ones as it requires a bit of implementation for :

  • Flickr uses OAuth to sign authenticated calls.
  • Flickr uses multipart to upload the photos, and does implemented the oauth mechanism by ignoring the binary (the photo) from the oauth signature generation.
  • Response handling : Flickr error-specific checking and payload extraction from generic response format, similar process as the google sample.
  • Param serialization : Flickr handle boolean as 0/1 values, we show here how to still use boolean argument and serialize them the way Flickr expects.

NB: The following are partial mappings of the available services and their main purpose is to give a quick example of a real world use case scenario of CRest usage, thus the mappings may not reflect all the services offered by the API.

Interface

This sample maps some of the Flickr's Rest APIs.

Below the mapped interface. Note: the mapping below only shows some mapped method, to have a look at all of them, refer to the sample source code.

@EndPoint("http://flickr.com")
@Path("/services")
@ResponseHandler(FlickrResponseHandler.class)
@POST
@ListSeparator(" ")
public interface Flickr {

    @Path("/rest")
    @QueryParam(value = "method", defaultValue = "flickr.galleries.create")
    Gallery newGallery(
            @FormParam("title") String title,
            @FormParam("description") String description);

    @Path("/rest")
    @QueryParam(value = "method", defaultValue = "flickr.photos.comments.addComment")
    String comment(
            @QueryParam("photo_id") long photoId,
            @QueryParam("comment_text") String comment);

    @Path("/rest")
    @QueryParam(value = "method", defaultValue = "flickr.photos.comments.getList")
    Comment[] getComments(@QueryParam("photo_id") long photoId);

    @Path("/upload")
    long uploadPhoto(@MultiPartParam(value="photo", contentType = "image/jpeg", fileName = "my-photo.jpeg") InputStream photo);

    @Path("/upload")
    long uploadPhoto(
            @MultiPartParam(value = "photo", contentType = "image/jpeg", fileName = "my-photo.jpeg") InputStream photo,
            @MultiPartParam("title") String title,
            @MultiPartParam("description") String description,
            @MultiPartParam("tags") String[] tags,
            @MultiPartParam("is_public") boolean isPublic,
            @MultiPartParam("is_friend") boolean isFriend,
            @MultiPartParam("is_family") boolean isFamily,
            @MultiPartParam("safety_level") SafetyLevel safetyLevel,
            @MultiPartParam("content_type") ContentType contentLype,
            @MultiPartParam("hidden") Visibility searchVisibility
    );


    @Path("/upload")
    @MultiPartParam(value = "async", defaultValue = "1")
    String asyncUploadPhoto(@MultiPartParam(value = "photo", contentType = "image/jpeg") File photo);

    @Path("/rest")
    @QueryParam(value = "method", defaultValue = "flickr.photos.upload.checkTickets")
    Uploader checkUploads(@QueryParam("tickets") String... tickets);

    (...)
}

And here's how to get an instance of the Flickr:

// Get a CRest instance. Should be done once.
String consumerKey = ...;
String consumerSecret = ...;
String accessToken = ...;
String accessTokenSecret = ...;

/* Get the factory */
CRest crest = CRest.oauth(consumerKey, consumerSecret, accessToken, accessTokenSecret)
                   .extractsEntityAuthParamsWith("multipart/form-data", new MultiPartEntityParamExtractor())
                   .deserializeXmlWith(JaxbDeserializer.class, Collections.<String,Object>singletonMap(MODEL_FACTORY_CLASS_PROP, FlickrModelFactory.class))
                   .bindSerializer(FlickrDateSerializer.class, Date.class)
                   .booleanFormat("1", "0")
                   .build();

// get a service instance
Flickr flickr = crest.build(Flickr.class);

// use it !
String ticket = flickr.asyncUploadPhoto(new File("/path/to/my/photo.jpg"));
(...)
Uploader upload = flickr.checkUploads(ticket);
(...)

Response Handler

Here is the code for the custom response handling. This class is not stricly necessary as we could have always returned the generic Response object for every method whatever happens, but this approach makes the interface looks better and less coupled to the flickr response format.

public class FlickrResponseHandler implements ResponseHandler {

    public final Object handle(Response context) throws Exception {
        /* Marshall the response */
        org.codegist.crest.flickr.model.Response res = context.to(org.codegist.crest.flickr.model.Response.class, Types.newType(org.codegist.crest.flickr.model.Response.class, Types.newType(SimplePayload.class, context.getExpectedGenericType())));

        /* Check for flickr OK status */
        if ("ok".equals(res.getStatus())) {
            /* Get the nested payload and returns it */
            Payload payload = res.getPayload();
            if (payload instanceof SimplePayload) {
                return ((SimplePayload) payload).getValue();
            } else {
                return payload;
            }
        } else {
            if (res.getPayload() instanceof Error) {
                /* Status is not OK, try to get the error cause */
                Error error = ((Error) res.getPayload());
                throw new CRestException(error.getMsg() + " (code=" + error.getCode() + ")");
            } else {
                /* Response format is not the one expected. */
                throw new CRestException("Unkown error");
            }
        }
    }


}

Model & Sources

The data model used by these samples hasn't been documented in this page as it only limits itself to plain java bean objects. The model have been deduced from the API response format and documentation and isn't guaranteed to reflect the full available model the API offers.

Do get a look at it, please refer to the sample source code HTML-based version.

This code is part of a project containing more sample, go to the project home page to get more information.