React.js and Spring Data REST: Part 4 - Events
To see updates to this code, visit our React.js and Spring Data REST tutorial. |
In the previous session, you introduced conditional updates to avoid collisions with other users when editing the same data. You also learned how to version data on the backend with optimistic locking. You got a tip off if someone edited the same record so you could refresh the page and get the update.
That’s good. But do you know what’s even better? Having the UI dynamically respond when other people update the resources.
In this session you’ll learn how to use Spring Data REST’s built in event system to detect changes in the backend and publish updates to ALL users through Spring’s WebSocket support. Then you’ll be able to dynamically adjust clients as the data updates.
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.
Adding Spring WebSocket support to the project
Before getting underway, you need to add a dependency to your project’s pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
This bring in Spring Boot’s WebSocket starter.
Configuring WebSockets with Spring
Spring comes with powerful WebSocket support. One thing to recognize is that a WebSocket is a very low level protocol. It does little more than offer the means to transmit data between client and server. The recommendation is to use a sub-protocol (STOMP for this session) to actually encode data and routes.
The follow code is used to configure WebSocket support on the server side:
@Component
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
static final String MESSAGE_PREFIX = "/topic";
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/payroll").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker(MESSAGE_PREFIX);
registry.setApplicationDestinationPrefixes("/app");
}
}
-
@EnableWebSocketMessageBroker
turns on WebSocket support. -
AbstractWebSocketMessageBrokerConfigurer
provides a convenient base class to configure basic features. - MESSAGE_PREFIX is the prefix you will prepend to every message’s route.
-
registerStompEndpoints()
is used to configure the endpoint on the backend for clients and server to link (/payroll
). -
configureMessageBroker()
is used to configure the broker used to relay messages between server and client.
With this configuration, it’s now possible to tap into Spring Data REST events and publish them over a WebSocket.
Subscribing to Spring Data REST events
Spring Data REST generates several application events based on actions occurring on the repositories. The follow code shows how to subscribe to some of these events:
@Component
@RepositoryEventHandler(Employee.class)
public class EventHandler {
private final SimpMessagingTemplate websocket;
private final EntityLinks entityLinks;
@Autowired
public EventHandler(SimpMessagingTemplate websocket,
EntityLinks entityLinks) {
this.websocket = websocket;
this…
This Week in Spring - October 13, 2015
Welcome to another installation of This Week in Spring! This week I'm in Krakow, Poland, for JDD and then it's off to St. Petersburg, Russia for the Joker conference!
We've got a lot to cover so let's get to it!
- After an extensive gestation period, one of our mad scientists Andy Wilkinson just announced the first GA release of the Spring REST Docs project which makes it easy to pull together automatic and human-augmented API documentation based on the tests used to exercise the APIs under test. Spring REST Docs has become a runaway success and it's definitely worth your time.
- Spring Tool Suite lead Martin Lippert just published a nice blog on the powerful local Spring Boot applications feature in STS
- Dr. Mark Pollack just announced the release of Spring XD 1.3M1 which…
The Spring Boot Dashboard in STS - Part 1: Local Boot Apps
Welcome Spring community,
This is the first of three blog entries introducing you to the new Spring Boot Dashboard in STS. You will see how to use the Spring Boot Dashboard in the IDE, learn about the various features it provides, and how it helps you while developing applications based on Spring Boot. Since the Spring Boot Dashboard was introduced in the recently released STS 3.7.1, you will need that version to follow this blog series. If you don't have that installed yet, please go to http://spring.io/tools/ and grab your copy of it.
Introduction
Spring Boot is now a widely adopted technology to simplify your life when implementing Spring applications for the enterprise. Especially suitable for creating microservice-based applications, it has changed the way we think about small and easy to configure Spring applications dramatically. Together with Spring Cloud, it opens the door to truly cloud-native applications, composed out of probably many microservices.
This dramatic shift in our architectural thinking needs to be reflected in our IDEs as well. Most of our traditional Java IDEs out there were invented not only in the pre-cloud-native era, but in the pre-cloud and to a certain degree in the pre-distributed era of programming. The same is true for the Spring Tool Suite and its base, the Eclipse IDE. It is time to push those IDEs into the cloud-native era. This was the starting point for the Spring Boot Dashboard. Its focus is to help you deal with a potentially larger number of Spring-Boot-based microservice applications and make your life as a developer a lot easier when working on those projects in your IDE.
The Spring Boot Dashboard
Starting small and incrementally, the Spring Boot Dashboard comes as an additional view in STS/Eclipse. You can open it by pressing the Spring Boot button in your main toolbar. It opens up a simple view that is in sync with your workspace projects, showing those projects of your workspace that are Spring Boot projects.
The main purpose of the Boot Dashboard is to give you quick access to the things you do every day, every hour, or even more frequently. You can quickly start your boot apps (in run or debug mode) by selecting them in the boot dashboard and pressing the "run" or "debug" action in the toolbar. There is no faster way to launch your boot app than this. And since you probably are going to change code and want to restart your app, the action lets you restart your boot app, if it is already running. Change your code, press the "run" button in the boot dashboard, and your boot app gets stopped and restarted for you. Again, a simple one-click action.
The great thing about these actions (and many more) in the boot dashboard is that they operate on single or multiple projects at the same time. If you want to start or stop a bunch of boot apps at the same time, for example to startup a set of collaborating services, just select them all in the dashboard and press "run". That's it.
As soon as you adopt Spring Boot 1.3 in your projects, you will notice additional goodies showing up in the Boot Dashboard. As soon as your boot app is being started, the boot dashboard visualizes that the app is starting - and it distinguishes between its startup phase (the VM is running, but the app is still initializing) and it is truly running and ready to use. The progress icon indicates the app is still starting up, the green "up" icon shows up as soon as the app is fully initialized and running. You don't need to observe the log output until some "server started" message shows up or something like that. The boot dashboards icons will let you know.
Once the app is running, the port that it listens on will show up in the boot dashboard - for your convenience. You don't have to scan the log output anymore to find out what port is being used by the app. The dashboard displays that information automatically. And in case you would like to jump to the console output of a running boot app, there is a quick action for that as well.
Often there is no need anymore to know about the port of a running app - since you don't have to open a browser tab for the app yourself. Double-click on the project in the boot dashboard and it will open a new browser tab for you - directly navigating to the apps default URL.
By default, this opens an Eclipse/STS internal browser view. If you prefer to use an external browser, you can set this in the preferences.
In case this default URL is not the one you would like to visit by default, you can customize that. Open the properties view, select the project in the boot dashboard and enter the default URL extension that you prefer. The double-click will open the default URL of the app + your customized extension to it.
In case you are not sure what URL extensions your application defines, you can select the “Request Mappings” tab in the properties view. All the request mappings of the running app are listed - your self-defined ones at the top, the ones coming from libraries at the bottom of that list. Double-clicking on the URL extension opens a browser for that extension, double-clicking on the code pointer opens the corresponding file of your project in an editor and jumps to the line that defines the request mapping.
The more microservice projects you have in your workspace, the more likely it is that you don’t work on all of them at the same time. You would like to focus on a subset. In Eclipse/STS, you might have created a working set, for example. The boot dashboard allows you to tag projects with an arbitrary number of tags (again, in the properties view). Those tags can then be used in the filter box (at the top of the boot dashboard) to reduce the number of projects that show up in the boot dashboard.
Outlook
The second part of this series will introduce you to the Cloud Foundry integration of the Boot dashboard, how to deploy microservices to CF from within the boot dashboard, and how to use local boot apps in combination with those deployed on CF.
This Week in Spring - October 6th, 2015
Welcome to another installation of This Week in Spring! As usual we've got a lot to cover this week so let's get to it!
- I love the new Spring Initializr!
- Spring Tool Suite lead Martin Lippert just announced STS 3.7.1
- Spring framework lead Juergen Hoeller has put together a lovely post that speaks to how to read claimed Java EE 7 proliferation
- Jaime Lopez - who was in some of my talks at Spring I/O in Barcelona, Spain, earlier this year - wrote an amazing introduction to Spring Boot - check it out!
- This blog nicely introduces using Spring's
AbstractFeedView
, powered by the ROME RSS and Atom library, to build feeds for a web application - Want to run Spring Boot on the Glassfish-powered Payara Micro?
- Hey, the ProgrammingFree YouTube video channel has a nice post …
Evolving Spring Initializr
We're happy to release today the new version of Spring Initializr at https://start.spring.io !
What started out as a small, in-house web application that generates Spring Boot projects, grew into something bigger than we expected. You can now use Spring Initializr on the web, in your favorite IDE (Eclipse STS and IntelliJ IDEA) and even with your command-line tools (try curl https://start.spring.io
).
In the meantime, the Spring portfolio is growing and we received a lot of useful feedback from the Spring community. Because nothing beats actual data, we've improved the service to export its metrics to a centralized redis instance, before the summer. This allows us to keep a reliable set of statistics for a long period of activity (and regardless of the number of instances we deploy on Pivotal Web Services…
This Week in Spring - September 29, 2015
Welcome to another installation of This Week in Spring! To those of you reading from the US, let me be the first to wish you a very happy national coffee day! As usual, we've got a lot to cover so let's get to it!
- have you been checking out the Annotated Spring site? It's wonderful! Packed with easily digsted screencasts on getting started with Spring (sort of like the Rails Casts of yore)
- our pal Greg Turnquist is at it again, with part 3 of his epic React.js and Spring Data REST tutorial
- not one to relax, Greg also posted an awesome new guide on building CRUD applications with Vaadin and Spring Boot
- Spring Data ninja Thomas Risberg has just announced Spring for Apache Hadoop 2.3 M3
- Spring Integration Java Config DSL lead Artem Bilan just announced the 1.1 GA release! This is a huge…
React.js and Spring Data REST: Part 3 - Conditional Operations
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.
@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.
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
});
});
},
-
The
follow()
function goes to the employees collection resource. -
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.
-
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. -
The
then(employeePromises ⇒ …)
clause takes the array of GET promises and merges them into a single promise withwhen.all()
, resolved when all the GET promises are resolved. -
loadFromServer
wraps up withdone(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.
var UpdateDialog = React.createClass({
handleSubmit: function (e) {
e.preventDefault();
var updatedEmployee = {};
this.props.attributes.forEach(attribute => {
updatedEmployee[attribute] = React.findDOMNode(this.refs[attribute]).value.trim…
Check out the new "Creating CRUD UI with Vaadin" guide
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!
More guides coming
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…
This Week in Spring - September 22nd, 2015
Welcome to another installment of This Week in Spring! This week, fresh after an incredible SpringOne2GX 2015, I'm.. a little burnt if I'm honest! :D BUT, Spring endures and I'm this week in Amsterdam with our pal Martin Deinum helping a large group of developers make the cloud native journey with Spring Boot, Spring Cloud and Cloud Foundry.
- Spring Boot co-lead Phillip Webb announced that Spring Boot 1.2.6 is now available!. Also interesting: this release was done live on stage at SpringOne2GX 2015! (Thanks JFrog!)
- our pal Matti Tahvonen has just posted guest blog on the Spring IO blog on how to use the recently 1.0 Spring Boot & Vaadin integration
- the first Spring Cloud Brixton milestone is now available complete with support for Zookeeper Discovery, Consul Discovery, Lattice Discovery, cluster leadership election and locks, and distributed tracing support
- Niklas Heidloff has put together a post on deploying a Spring Boot application to Bluemix using Docker in 20 minutes…
Java DSL for Spring Integration 1.1 GA is Available
Dear Spring Community!
On behalf of Spring Integration team I'm pleased to announce that the 1.1 GA of Spring Integration Java DSL is now available from the Release Repository and Maven Central:
For Gradle use this dependency:
'org.springframework.integration:spring-integration-java-dsl:1.1.0.RELEASE'
For Maven this:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
First of all a big thanks to everyone who visited my talk at the SpringOne 2GX 2015 last week…