Greg L. Turnquist

Greg L. Turnquist

Alumni
Recent Blog posts by Greg L. Turnquist

React.js and Spring Data REST: Part 3 - Conditional Operations

Engineering | September 29, 2015 | ...
To see updates to this code, visit our React.js and Spring Data REST tutorial.

In the previous session, you found out how to turn on Spring Data REST’s hypermedia controls, have the UI navigate by paging, and dynamically resize based on changing the page size. You added the ability to create and delete employees and have the pages adjust. But no solution is complete with taking into consideration updates made by other users on the same bit of data you are currently editing.

Feel free to grab the code from this repository and follow along. This session is based on the previous session’s app with extra things added.

To PUT or not to PUT, that is the question

When you fetch a resource, there is risk is that it might go stale if someone else updates it. To deal with this, Spring Data REST integrates two technologies: versioning of resources and ETags.

By versioning resources on the backend and using ETags in the frontend, it is possible to conditially PUT a change. In other words, you can detect if a resource has changed and prevent a PUT (or a PATCH) from stomping on someone else’s update. Let’s check it out.

Versioning REST resources

To support versioning of resources, define a version attribute for your domain objects that need this type of protection.

src/main/java/com/greglturnquist/payroll/Employee.java
@Data
@Entity
public class Employee {
private @Id @GeneratedValue Long id;
private String firstName;
private String lastName;
private String description;

private @Version @JsonIgnore Long version;

private Employee() {}

public Employee(String firstName, String lastName, String description) {
	this.firstName = firstName;
	this.lastName = lastName;
	this.description = description;
}

}

  • The version field is annoated with javax.persistence.Version. It causes a value to be automatically stored and updated everytime a row is inserted and updated.

When fetching an individual resource (not a collection resource), Spring Data REST will automatically add an ETag response header with the value of this field.

Fetching individual resources and their headers

In the previous session you used the collection resource to gather data and populate the UI’s HTML table. With Spring Data REST, the _embedded data set is considered a preview of data. While useful for glancing at data, to get headers like ETags, you need to fetch each resource individually.

In this version, loadFromServer is updated to fetch the collection and then use the URIs to retrieve each individual resource.

src/main/resources/static/app.jsx - Fetching each resource
loadFromServer: function (pageSize) {
    follow(client, root, [
        {rel: 'employees', params: {size: pageSize}}]
    ).then(employeeCollection => {
        return client({
            method: 'GET',
            path: employeeCollection.entity._links.profile.href,
            headers: {'Accept': 'application/schema+json'}
        }).then(schema => {
            this.schema = schema.entity;
            this.links = employeeCollection.entity._links;
            return employeeCollection;
        });
    }).then(employeeCollection => {
        return employeeCollection.entity._embedded.employees.map(employee =>
                client({
                    method: 'GET',
                    path: employee._links.self.href
                })
        );
    }).then(employeePromises => {
        return when.all(employeePromises);
    }).done(employees => {
        this.setState({
            employees: employees,
            attributes: Object.keys(this.schema.properties),
            pageSize: pageSize,
            links: this.links
        });
    });
},
  1. The follow() function goes to the employees collection resource.
  2. The then(employeeCollection ⇒ …​) clause creates a call to fetch JSON Schema data. This has a sub-then clause to store the metadata and navigational links in the <App/> component.
    • Notice that this embedded promise returns the employeeCollection. That way, the collection can be passed onto the next call while letting you grab the metadata along the way.
  3. The second then(employeeCollection ⇒ …​) clause converts the collection of employees into an array of GET promises to fetch each individual resource. This is what you need to fetch an ETag header for each employee.
  4. The then(employeePromises ⇒ …​) clause takes the array of GET promises and merges them into a single promise with when.all(), resolved when all the GET promises are resolved.
  5. loadFromServer wraps up with done(employees ⇒ …​) where the UI state is updated using this amalgamation of data.

This chain is implemented in other places as well. For example, onNavigate(), which is used to jump to different pages, has been updated to fetch individual resources. Since it’s mostly the same as what’s shown above, it’s been left out of this session.

Updating existing resources

In this session, you are adding an UpdateDialog React component to edit existing employee records.

src/main/resources/static/app.jsx - UpdateDialog component
var UpdateDialog = React.createClass({
handleSubmit: function (e) {
    e.preventDefault();
    var updatedEmployee = {};
    this.props.attributes.forEach(attribute =&gt; {
        updatedEmployee[attribute] = React.findDOMNode(this.refs[attribute]).value.trim…

Check out the new "Creating CRUD UI with Vaadin" guide

Engineering | September 28, 2015 | ...

Greetings Spring community,

Today we have published a new guide: Creating CRUD UI with Vaadin.

This guide, written by the Vaadin team, shows how to nicely build a UI that taps into Spring Data, but doesn't require writing a single line of JavaScript or HTML code.

Vaadin is real cool:

  • Comes with its own Spring Boot starter
  • Works nicely with constructor injection
  • Makes it dirt simple to plugin persistence solutions like Spring Data
  • Is armed with an arsenal of plugins to grow into real applications

Check out this newly minted guide and have fun!

As a follow up to SpringOne 2GX, we have identified some more guides that need to be written. The story of cloud native is sweeping the development community, and people are asking for more solutions. Our job shouldn't be racking and stacking servers or building infrastructure. Instead, we should focus on smooth and easy solutions. Coding things cloud native

React.js and Spring Data REST: Part 2 - Hypermedia

Engineering | September 15, 2015 | ...
To see updates to this code, visit our React.js and Spring Data REST tutorial.

In the previous session, you found out how to stand up a backend payroll service to store employee data using Spring Data REST. A key feature it lacked was using the hypermedia controls and navigation by links. Instead, it hard coded the path to find data.

Feel free to grab the code from this repository and follow along. This session is based on the previous session’s app with extra things added.

In the beginning there was data…​and then there was REST

I am getting frustrated by the number of people calling any HTTP-based interface a REST API. Today’s example is the SocialSite REST API. That is RPC. It screams RPC…​.What needs to be done to make the REST architectural style clear on the notion that hypertext is a constraint? In other words, if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period. Is there some broken manual somewhere that needs to be fixed?

So, what exactly ARE hypermedia controls, i.e. hypertext, and how can you use them? To find out, let’s take a step back and look at the core mission of REST.

The concept of REST was to borrow ideas that made the web so successful and apply them to APIs. Despite the web’s vast size, dynamic nature, and low rate that clients, i.e. browsers, are updated, the web is an amazing success. Roy Fielding sought to use some of its constraints and features and see if that would afford similar expansion of API production and consumption.

One of the constraints is to limit the number of verbs. For REST, the primary ones are GET, POST, PUT, DELETE, and PATCH. There are others, but we won’t get into them here.

  • GET - fetch the state of a resource without altering the system
  • POST - create a new resource without saying where
  • PUT - replace an existing resource, overwriting whatever else is already there (if anything)
  • DELETE - remove an existing resource
  • PATCH - alter an existing resource partially

These are standardized HTTP verbs with well written specs. By picking up and using already coined HTTP operations, we don’t have to invent a new language and educate the industry.

Another constraint of REST is to use media types to define the format of data. Instead of everyone writing their own dialect for the exchange of information, it would be prudent to develop some media types. One of the most popular ones to be accepted is HAL, media type application/hal+json. It is Spring Data REST’s default media type. A keen value is that there is no centralized, single media type for REST. Instead, people can develop media types and plug them in. Try them out. As different needs become available, the industry can flexibly move.

A key feature of REST is to include links to relevant resources. For example, if you were looking at an order, a RESTful API would include a link to the related customer, links to the catalog of items, and perhaps a link to the store from which the order was placed. In this session, you will introduce paging, and see how to also use navigational paging links.

Turning on paging from the backend

To get underway with using frontend hypermedia controls, you need to turn on some extra controls. Spring Data REST provides paging support. To use it, just tweak the repository definition:

src/main/java/com/greglturnquist/payroll/EmployeeRepository.java
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {

}

Your interface now extends PagingAndSortingRepository which adds extra options to set page size, and also adds navigational links to hop from page to page. The rest of the backend is the same (exception for some extra pre-loaded data to make things interesting).

Restart the application (./mvnw spring-boot:run) and see how it works.

$ curl localhost:8080/api/employees?size=2
{
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/api/employees?page=0&size=2"
    },
    "self" : {
      "href" : "http://localhost:8080/api/employees"
    },
    "next" : {
      "href" : "http://localhost:8080/api/employees?page=1&size=2"
    },
    "last" : {
      "href" : "http://localhost:8080/api/employees?page=2&size=2"
    }
  },
  "_embedded" : {
    "employees" : [ {
      "firstName" : "Frodo",
      "lastName" : "Baggins",
      "description" : "ring bearer",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/1"
        }
      }
    }, {
      "firstName" : "Bilbo",
      "lastName" : "Baggins",
      "description" : "burglar",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/api/employees/2"
        }
      }
    } ]
  },
  "page" : {
    "size" : 2,
    "totalElements" : 6,
    "totalPages" : 3,
    "number" : 0
  }
}

The default page size is 20, so to see it in action, ?size=2 applied. As expected, only two employees are listed. In addition, there is also a first, next, and last link. There is also the self link, free of context including page parameters.

If you navigate to the next link, you’ll then see a prev link as well:

$ curl "http://localhost:8080/api/employees?page=1&size=2"
{
  "_links" : {
    "first" : {
      "href" : "http://localhost:8080/api/employees?page=0&size=2"
    },
    "prev" : {
      "href" : "http://localhost:8080/api/employees?page=0&size=2"
    },
    "self" : {
      "href" : "http://localhost:8080/api/employees"
    },
    "next" : {
      "href" : "http://localhost:8080/api/employees?page=2&size=2"
    },
    "last" : {
      "href" : "http://localhost:8080/api/employees?page=2&size=2"
    }
  },
...
Note
When using "&" in URL query parameters, the command line thinks it’s a line break. Wrap the whole URL with quotation marks to bypass that.

That looks neat, but it will be even better when you update the frontend to take advantage of that.

Navigating by relationship

That’s it! No more changes are needed on the backend to start using the hypermedia controls Spring Data REST provides out of the box. You can switch to working on the frontend. (That’s part of the beauty of Spring Data REST. No messy controller updates!)

Note
It’s important to point out, this application isn’t "Spring Data REST-specific." Instead, it uses HAL, URI Templates, and other standards. That’s how using rest.js is a snap: that library comes with HAL support.

In the previous session, you hardcoded the path to /api/employees. Instead, the ONLY path you should hardcode is the root.

...
var root = '/api';
...

With a handy little follow() function, you can now start from the root and navigate to where you need!

componentDidMount: function () {
    this.loadFromServer(this.state.pageSize);
},

In the previous session, the loading was done directly inside componentDidMount(). In this session, we are making it possible to reload the entire list of employees when the page size is updated. To do so, we have moved things into loadFromServer().

loadFromServer: function (pageSize) {
    follow(client, root, [
        {rel: 'employees', params: {size: pageSize}}]
    ).then(employeeCollection => {
        return client({
            method: 'GET',
            path: employeeCollection.entity._links.profile.href,
            headers: {'Accept': 'application/schema+json'}
        }).then(schema => {
            this.schema = schema.entity;
            return employeeCollection;
        });
    }).done(employeeCollection => {
        this.setState({
            employees: employeeCollection.entity._embedded.employees,
            attributes: Object.keys(this.schema.properties),
            pageSize: pageSize,
            links: employeeCollection.entity._links});
    });
},

loadFromServer is very similar the previous session, but instead if uses follow():

  • The first argument to the follow() function is the client object used to make REST calls.
  • The second argument is the root URI to start from.
  • The third argument is an array of relationships to navigate along. Each one can be a string or an object.

The array of relationships can be as simple as ["employees"], meaning when the first call is made, look in _links for the relationship (or rel) named employees. Find its href and navigate to it. If there is another relationship in the array, rinse and repeat.

Sometimes, a rel by itself isn’t enough. In this fragment of code, it also plugs in a query parameter of ?size=<pageSize>. There are other options that can be supplied, as you’ll see further along.

Grabbing JSON Schema metadata

After navigating to employees with the size-based query, the employeeCollection is at your fingertips. In the previous session, we called it day and displayed that data inside <EmployeeList />. Today, you are performing another call to grab some JSON Schema metadata found a /api/profile/employees.

You can see the data yourself:

$ curl http://localhost:8080/api/profile/employees -H 'Accept:application/schema+json'
{
  "title" : "Employee",
  "properties" : {
    "firstName" : {
      "title" : "First name",
      "readOnly" : false,
      "type" : "string"
    },
    "lastName" : {
      "title" : "Last name",
      "readOnly" : false,
      "type" : "string"
    },
    "description" : {
      "title" : "Description",
      "readOnly" : false,
      "type" : "string"
    }
  },
  "definitions" : { },
  "type" : "object",
  "$schema" : "http://json-schema.org/draft-04/schema#"
}
Note
The default form of metadata at /profile/employees is ALPS. In this case, though, you are using content negotation to fetch JSON Schema.

By capturing this information in the`<App />` component’s state, you can make good use of it later on when building input forms.

Creating new records

Equipped with this metadata, you can now add some extra controls to the UI. Create a new React component, <CreateDialog />.

var CreateDialog = React.createClass({
handleSubmit: function (e) {
    e.preventDefault();
    var newEmployee = {};
    this.props.attributes.forEach(attribute =&gt; {
        newEmployee[attribute] = React.findDOMNode(this.refs[attribute]).value.trim();
    });
    this.props.onCreate(newEmployee);

    // clear out the dialog's inputs
    this.props.attributes.forEach(attribute =&gt; {
        React.findDOMNode(this.refs[attribute]).value = '';
    });

    // Navigate away from the dialog to hide it.
    window.location = "#";
},

render: function () {
    var inputs = this.props.attributes.map(attribute…

React.js and Spring Data REST: Part 1 - Basic Features

Engineering | September 01, 2015 | ...
To see updates to this code, visit our React.js and Spring Data REST tutorial.

Welcome Spring community,

This is the first of several blog entries. In this session, you will see how to get a bare-bones Spring Data REST application up and running quickly. Then you will build a simple UI on top of it using Facebook’s React.js toolset.

Step 0 - Setting up your environment

Feel free to grab the code from this repository and follow along.

If you want to do it yourself, visit http://start.spring.io and pick these items:

  • Rest Repositories
  • Thymeleaf
  • JPA
  • H2

This demo uses Java 8, Maven Project, and the latest stable release of Spring Boot. This will give you a clean, empty project. From there, you can add the various files shown explicitly in this session, and/or borrow from the repository listed above.

In the beginning…​

In the beginning there was data. And it was good. But then people wanted to access the data through various means. Over the years, people cobbled together lots of MVC controllers, many using Spring’s powerful REST support. But doing over and over cost a lot of time.

Spring Data REST addresses how simple this problem can be if some assumptions are made:

  • The developer uses a Spring Data project that supports the repository model.
  • The system uses well accepted, industry standard protocols, like HTTP verbs, standardized media types, and IANA-approved link names.

Declaring your domain

The cornerstone of any Spring Data REST-based application are the domain objects. For this session, you will build an application to track the employees for a company. Kick that off by creating a data type like this:

src/main/java/com/greglturnquist/payroll/Employee.java
@Data
@Entity
public class Employee {
private @Id @GeneratedValue Long id;
private String firstName;
private String lastName;
private String description;

private Employee() {}

public Employee(String firstName, String lastName, String description) {
	this.firstName = firstName;
	this.lastName = lastName;
	this.description = description;
}

}

  • @Entity is a JPA annotation that denotes the whole class for storage in a relational table.
  • @Id and @GeneratedValue are JPA annotation to note the primary key and that is generated automatically when needed.
  • @Data and @RequiredArgsConstructor are Project Lombok annotations to autogenerate getters, setters, constructors, toString, hash, equals, and other things. It cuts down on the boilerplate.

This entity is used to track employee information. In this case, their name and job description.

Note
Spring Data REST isn’t confined to JPA. It supports many NoSQL data stores, but you won’t be covering those here.

Defining the repository

Another key piece of a Spring Data REST application is to create a corresponding repository definition.

src/main/java/com/greglturnquist/payroll/EmployeeRepository.java
public interface EmployeeRepository extends CrudRepository<Employee, Long> {

}

  • The repository extends Spring Data Commons' CrudRepository and plugs in the type of the domain object and its primary key

That is all that is needed! In fact, you don’t even have to annotate this invisible if its top-level and visible. If you use your IDE and open up CrudRepository, you’ll find a fist full of pre-built methods already defined.

Note
You can define your own repository if you wish. Spring Data REST supports that as well.

Pre-loading the demo

To work this this application, you need to pre-load it with some data like this:

src/main/java/com/greglturnquist/payroll/DatabaseLoader.java
@Component
public class DatabaseLoader implements CommandLineRunner {
private final EmployeeRepository repository;

@Autowired
public DatabaseLoader(EmployeeRepository repository) {
	this.repository = repository;
}

@Override
public void run(String... strings) throws Exception {
	this.repository.save(new Employee("Frodo", "Baggins…

Spring Guides Move to Java 8

Engineering | June 17, 2015 | ...

Perhaps you've noticed some recent articles lately?

Okay, those last two aren't articles, but were instead driven by the the rapid adoption of Java 8. Java 8 has been picked up by the development community FAST. Here on the Spring team, we believe strongly in adopting Java 8 for new applications. To support that and improve your own ability to move as well, we just updated all of the Spring Getting Started Guides

Check out Dave Syer's "Spring Security and AngularJS" blog series converted to tutorial

Engineering | April 02, 2015 | ...

Greetings Spring community,

Dave Syer's six-part blog series on Spring Security and AngularJS has been a smash hit! It has echoed across the twittersphere, torn up DZone, and drawn people far and wide.

Did you miss any of it? Perhaps you've heard of it and found it too difficult to track down the first post. No more.

Please navigate to our newly minted Spring Security and AngularJS tutorial and enjoy all that solid gold. We migrated 100% of it into that tutorial, made slight edits to the links, and polished it up just for you.

Share and enjoy!

Screencast: How to create a RESTful app in five minutes or less

Engineering | November 20, 2014 | ...

Recently, a friend of mine tweeted out a challenge:

"Name a framework in which you can create a new app expose a REST service with a database and deploy it to the cloud in five minutes. #grails"

The moment I spotted that tweet, I responded, "Spring Boot + Spring Data REST"! I realized he was kindly pointing out how easy it is to build RESTful services with Grails (a great framework). But I couldn't resist showing the ease and power of Spring Data REST.

To prove my point, I couldn't resisting crafting a screencast. In the linked screencast, I show how über easy Spring has made it to pick the parts for your app from http://start.spring.io, define your domain, and then…

See how to build, test, secure, and add hypermedia with this new tutorial, "Building REST Services with Spring"

Engineering | October 23, 2014 | ...

Greetings Spring Community!

Today we have released a new tutorial written by Spring geek Josh Long, the man who travels the globe talking about Spring: Building REST Services with Spring

In this sleek tutorial, you can read about the simplicity and power of building RESTful web services using Spring. You'll also see how to:

It's a really good read with LOTS of code (you know, the important stuff). What about the existing REST…

Join us at the Spring Data birds-of-a-feather session @springone2gx #s2gx

Engineering | September 05, 2014 | ...

Are you ready for SpringOne? It's almost here!

A popular part of SpringOne are the birds-of-a-feather sessions. Different groups get together to talk about different aspects of Spring, Groovy, and Grails. This year, they are scheduled for Tuesday night, September 9th, starting at 9pm. (When do they end? When everyone finally leaves!)

They are indeed popular. Last year I sat in on the Spring Framework one and enjoyed the close, unscripted discussions (not lectures). You should think about carving out some time for that!

This year, we have a new session planned: Spring Data.

If you aren't aware…

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all