Created
January 24, 2018 20:28
-
-
Save scathers/42ebd791eb6f120116896f1564fed57d to your computer and use it in GitHub Desktop.
Spring Boot Elide Integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cathers.controller; | |
import java.security.Principal; | |
import java.util.Map; | |
import javax.persistence.EntityManagerFactory; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.ws.rs.core.MultivaluedHashMap; | |
import javax.ws.rs.core.MultivaluedMap; | |
import org.hibernate.SessionFactory; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.http.ResponseEntity; | |
import org.springframework.transaction.annotation.Transactional; | |
import org.springframework.web.bind.annotation.RequestBody; | |
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.RestController; | |
import org.springframework.web.servlet.HandlerMapping; | |
import com.yahoo.elide.Elide; | |
import com.yahoo.elide.ElideResponse; | |
import com.yahoo.elide.ElideSettings; | |
import com.yahoo.elide.ElideSettingsBuilder; | |
import com.yahoo.elide.core.DataStore; | |
import com.yahoo.elide.datastores.hibernate5.*; | |
/** | |
* An example Spring Boot controller that uses Elide version 4 for a JSON API REST service. | |
* Based on: | |
* https://dzone.com/articles/create-a-json-api-rest-service-with-spring-boot-an | |
*/ | |
@RestController | |
@RequestMapping(path = ElideController.API_PREFIX, produces = ElideController.CONTENT_TYPE) | |
public class ElideController { | |
private static final Logger log = LoggerFactory.getLogger(ElideController.class); | |
public static final String API_PREFIX = "api"; | |
public static final String CONTENT_TYPE = "application/vnd.api+json"; | |
final EntityManagerFactory emf; | |
final SessionFactory sessionFactory; | |
final DataStore dataStore; | |
final ElideSettings elideSettings; | |
final Elide elide; | |
@Autowired | |
public ElideController(EntityManagerFactory emf) { | |
this.emf = emf; | |
sessionFactory = emf.unwrap(SessionFactory.class); | |
dataStore = new AbstractHibernateStore.Builder(sessionFactory).build(); | |
elideSettings = new ElideSettingsBuilder(dataStore).build(); | |
this.elide = new Elide(elideSettings); | |
} | |
/** | |
* We'll implement this interface as a lambda to make working with Elide easier | |
*/ | |
public interface ElideCallable { | |
ElideResponse call(final Elide elide, final String path); | |
} | |
/** | |
* All our elide operations require similar initialisation, which we perform in this method before | |
* calling elideCallable with the elide object and the path that elide needs to know what it is | |
* supposed to do. | |
* | |
* @param request The request | |
* @param elideCallable A callback that is used to execute elide | |
* @return The response to the client | |
*/ | |
private ResponseEntity<String> elideRunner(final HttpServletRequest request, | |
final ElideCallable elideCallable) { | |
// This gives us the full path that was used to call this endpoint. | |
final String restOfTheUrl = | |
((String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)) | |
// Remove the API prefix | |
.substring(("/" + API_PREFIX).length()); | |
final ElideResponse elideResponse = elideCallable.call(elide, restOfTheUrl); | |
return ResponseEntity.status(elideResponse.getResponseCode()).body(elideResponse.getBody()); | |
} | |
/** | |
* Converts a plain map to a multivalued map | |
* | |
* @param input The original map | |
* @return A MultivaluedMap constructed from the input | |
*/ | |
private MultivaluedMap<String, String> fromMap(final Map<String, String> input) { | |
return new MultivaluedHashMap<String, String>(input); | |
} | |
@RequestMapping(method = RequestMethod.GET, value = {"/{entity}", | |
"/{entity}/{id}/relationships/{entity2}", "/{entity}/{id}/{child}", "/{entity}/{id}"}) | |
@Transactional | |
public ResponseEntity<String> jsonApiGet(@RequestParam final Map<String, String> allRequestParams, | |
final HttpServletRequest request, final Principal principal) { | |
log.trace("GET Principal: {}", principal); | |
return elideRunner(request, | |
(elide, path) -> elide.get(path, fromMap(allRequestParams), principal)); | |
} | |
@RequestMapping(method = RequestMethod.POST, | |
value = {"/{entity}", "/{entity}/{id}/relationships/{entity2}"}) | |
@Transactional | |
public ResponseEntity<String> jsonApiPost(@RequestBody final String body, | |
final HttpServletRequest request, final Principal principal) { | |
return elideRunner(request, (elide, path) -> elide.post(path, body, principal)); | |
} | |
@RequestMapping(method = RequestMethod.DELETE, | |
value = {"/{entity}/{id}", "/{entity}/{id}/relationships/{entity2}"}) | |
@Transactional | |
public ResponseEntity<String> jsonApiDelete(@RequestBody(required = false) final String body, | |
final HttpServletRequest request, final Principal principal) { | |
return elideRunner(request, (elide, path) -> elide.delete(path, body, principal)); | |
} | |
@RequestMapping(method = RequestMethod.PATCH, | |
value = {"/{entity}/{id}", "/{entity}/{id}/relationships/{entity2}"}) | |
@Transactional | |
public ResponseEntity<String> jsonApiPatch(@RequestBody final String body, | |
final HttpServletRequest request, final Principal principal) { | |
/* | |
* Note that the patch operation here is the standard update, not the JSON Patch extension | |
* (http://jsonapi.org/extensions/jsonpatch/) | |
*/ | |
return elideRunner(request, | |
(elide, path) -> elide.patch(CONTENT_TYPE, CONTENT_TYPE, path, body, principal)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment