com.orangeandbronze.jblubble.sample.PersonController.java Source code

Java tutorial

Introduction

Here is the source code for com.orangeandbronze.jblubble.sample.PersonController.java

Source

/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.orangeandbronze.jblubble.sample;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartFile;

import com.orangeandbronze.jblubble.BlobInfo;
import com.orangeandbronze.jblubble.BlobKey;
import com.orangeandbronze.jblubble.BlobstoreException;
import com.orangeandbronze.jblubble.BlobstoreService;

@RequestMapping("/" + PersonController.PATH)
@Controller
@Transactional
public class PersonController {

    public static final String PATH = "persons";

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private BlobstoreService blobstoreService;

    // Ideally, persistence should NOT be part of the presentation layer.
    // But since this is just an example, we've simplified things here.
    // private PersonService service;

    /**
     * Retrieves the person with the given id. Throwing an
     * IllegalArgumentException if there is no such person.
     * 
     * @param id
     *            the given id
     * @return the person with the given id
     */
    protected Person getPersonById(String id) {
        Person person = null;
        try {
            Long personId = Long.valueOf(id);
            if (logger.isDebugEnabled()) {
                logger.debug("Retrieving Person with id=[{}]", personId);
            }
            person = entityManager.find(Person.class, personId);
        } catch (NumberFormatException e) {
            if (logger.isWarnEnabled()) {
                logger.warn("Invalid number format: {}", id);
            }
        }
        if (person == null) {
            throw new IllegalArgumentException();
        }
        return person;
    }

    protected List<Person> getAllPersons() {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Person> criteriaQuery = criteriaBuilder.createQuery(Person.class);
        criteriaQuery.select(criteriaQuery.from(Person.class));
        return entityManager.createQuery(criteriaQuery).getResultList();
    }

    protected BlobKey createPhotoBlob(MultipartFile photoFile) {
        BlobKey blobKey = null;
        if (photoFile.isEmpty()) {
            blobKey = null;
        } else {
            try {
                InputStream inputStream = photoFile.getInputStream();
                try {
                    blobKey = blobstoreService.createBlob(inputStream, photoFile.getOriginalFilename(),
                            photoFile.getContentType());
                } finally {
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.error("Error saving person's photo", e);
            }
        }
        return blobKey;
    }

    @RequestMapping(method = RequestMethod.GET)
    public String list(Model model) {
        model.addAttribute("persons", getAllPersons());
        return PATH + "/list";
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    public String show(@PathVariable("id") String id, Model model) {
        Person person = getPersonById(id);
        model.addAttribute("person", person);
        return PATH + "/show";
    }

    @RequestMapping(method = RequestMethod.GET, value = "/create")
    public String create(Model model) {
        model.addAttribute("person", new Person());
        return PATH + "/create";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String save(@ModelAttribute Person person, @RequestParam("photo") MultipartFile photoFile) {
        if (logger.isDebugEnabled()) {
            logger.debug("Saving {}", person);
        }
        BlobKey blobKey = createPhotoBlob(photoFile);
        person.setPhotoId(blobKey);
        entityManager.persist(person);
        return "redirect:" + PATH;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}/edit")
    public String edit(@PathVariable("id") String id, Model model) {
        Person person = getPersonById(id);
        model.addAttribute("person", person);
        return PATH + "/edit";
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    public String update(@PathVariable("id") String id, @ModelAttribute Person updatedPerson,
            @RequestParam("photo") MultipartFile photoFile) {
        if (logger.isDebugEnabled()) {
            logger.debug("Saving {}", updatedPerson);
        }
        Person existingPerson = getPersonById(id);
        // Merge updatedPerson with existingPerson
        existingPerson.setName(updatedPerson.getName());
        BlobKey blobKey = createPhotoBlob(photoFile);
        if (existingPerson.getPhotoId() != null) {
            blobstoreService.delete(existingPerson.getPhotoId());
        }
        existingPerson.setPhotoId(blobKey);
        // Changes to existingPerson will automatically be persisted
        return "redirect:" + PATH;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}/photo")
    public void servePhoto(@PathVariable("id") String id, WebRequest webRequest, HttpServletResponse response)
            throws BlobstoreException, IOException {
        Person person = getPersonById(id);
        if (person != null) {
            BlobKey photoId = person.getPhotoId();
            if (photoId != null) {
                BlobInfo blobInfo = blobstoreService.getBlobInfo(photoId);
                if (webRequest.checkNotModified(blobInfo.getDateCreated().getTime())) {
                    return;
                }
                response.setContentType(blobInfo.getContentType());
                // In Servlet API 3.1, use #setContentLengthLong(long)
                response.setContentLength((int) blobInfo.getSize());
                response.setDateHeader("Last-Modified", blobInfo.getDateCreated().getTime());
                // response.addHeader("Cache-Control", "must-revalidate, max-age=3600");
                blobstoreService.serveBlob(photoId, response.getOutputStream());
                return;
            }
        }
        throw new IllegalArgumentException();
    }

    /**
     * Maps IllegalArgumentExceptions to a 404 Not Found HTTP status code.
     */
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler({ IllegalArgumentException.class })
    public void handleNotFound() {
        // just return empty 404
    }

}