Posted in Software Engineering

S3 vs EBS vs EFS

Amazon Web Services (AWS) is well-known for its vast number of product offerings. There are (probably) a few AWS ninjas who know exactly how and when to use which Amazon product for what. The rest of us are in need of help.

Specifically in the storage arena, AWS provides three popular services — S3, Elastic Block Store (EBS), and Elastic File System (EFS) — which work quite differently and offer different levels of performance, cost, availability, and scalability. We’ll discuss the use cases of these storage options, and compare their performance, cost, and accessibility to stored data.

AWS Storage Options: A Primer

  • Amazon S3 provides simple object storage, useful for hosting website images and videos, data analytics, and both mobile and web applications. Object storage manages data as objects, meaning all data types are stored in their native formats. There is no hierarchy of relations between files with object storage — data objects can be distributed across several machines. You can access the S3 service from anywhere on the internet.
  • AWS EBS provides persistent block-level data storage. Block storage stores files in multiple volumes called blocks, which act as separate hard drives; block storage devices are more flexible and offer higher performance than regular file storage. You need to mount EBS onto an Amazon EC2 instance. Use cases include business continuity, software testing, and database management.
  • AWS EFS is a shared, elastic file storage system that grows and shrinks as you add and remove files. It offers a traditional file storage paradigm, with data organized into directories and subdirectories. EFS is useful for SaaS applications and content management systems. You can mount EFS onto several EC2 instances at the same time.

The following diagram illustrates the difference between object storage and block storage.

Image title

Image Source: NetApp Cloud (used with permission)

Head to Head

The table below compares Amazon S3, EBS, and EFS in terms of performance, cost, availability, accessibility, access control, and storage or file size limits enforced by each service.

Image title

Which AWS Cloud Storage Service Is Best?

As always, it depends.

  • Amazon S3 is cheapest for data storage alone. However, there are various other pricing parameters in S3, including cost per number of requests made, S3 Analytics, and data transfer out of S3 per gigabyte. EFS has the simplest cost structure.
  • Amazon S3 can be accessed from anywhere. AWS EBS is only available in a particular region, while you can share files between regions on multiple EFS instances.
  • EBS and EFS are both faster than Amazon S3, with high IOPS and lower latency.
  • EBS is scalable up or down with a single API call. Since EBS is cheaper than EFS, you can use it for database backups and other low-latency interactive applications that require consistent, predictable performance.
  • EFS is best used for large quantities of data, such as large analytic workloads. Data at this scale cannot be stored on a single EC2 instance allowed in EBS—requiring users to break up data and distribute it between EBS instances. The EFS service allows concurrent access to thousands of EC2 instances, making it possible to process and analyze large amounts of data seamlessly.
Posted in Software Engineering

Advanced Tips & Tricks to Optimize your Terraform Code

https://medium.com/slalom-technology/how-to-optimize-network-infrastructure-code-in-terraform-fff16fada668

Deployment and management infrastructure day-to-day isn’t an easy task. In this post, I’ll discuss how we can accomplish this using Terraform in AWS and my hope is that this post will bring in more confidence in using Terraform and open up possible approaches and solutions. I will demonstrate how to build complex infrastructures and how to avoid duplication in code using loops. My example will be focused on Amazon Web Services (AWS), but all the information should apply to other clouds as well.

Terraform is a tool created by HashiCorp that allows you to:

  • describe your infrastructure as code
  • outline exactly what will happen when you run your code
  • builds a graph of your resources
  • create and change your infrastructure with minimal human interaction.

Terraform is platform-agnostic and you can use it to manage bare metal or cloud servers — like AWS, GCP, OpenStack, Azure, etc…

Terraform uses a declarative language, called HashiCorp Configuration Language (HCL), to define an infrastructure. This allows for a cleaner, more authentic view of what is being deployed.

Specific types of tasks, like loops and if-statements, could become extra painful since declarative languages usually don’t have loops. With that in mind, defining multiple resources that are similar could end up looking like this.

Example of common needs to create multiple similar resources

The loop is used to eliminate the workload in terms of programming and for faster execution without consuming extra time coding.

Is there a better way?

Almost every Terraform resource has a metadata parameter. “count” is one of the parameters which simplifies configurations to scale your resources by simply incrementing a number. In the example below, I am using the function “length()” to calculate the number of values in my list.

Example “count” use

List

What if you wanted to give each resource a unique name?

To accomplish this, you can simply use “count.index”.

Example of “count.index”

I will show you how to optimize code with multiple examples of count and splat expression for the diagram below and provide you with the code.

For the code to work, minimum pre-requirements must be met:

  • Terraform version >= 0.11.7
  • AWS Account with the right level of permission
  • Visual Studio Code or Sublime

The following layout is typical of what you find in many data centers with DMZ (Public) & Internal (Application and Database)networks. This diagram is a cloud agnostic 3-tiered solution which has public, application, and database subnets in multi availability zones. I will also show how I used splat expressions to configure Auto Scaling for Bastion host.

The Network topology above display of what will be implemented:

  • VPC
  • Subnets
  • Availability Zone
  • NAT Gateway
  • Route Tables
  • Security Group
  • Internet Gateway
  • Auto Scaling Bastion host

Code Review

Global variables

  • Self-explanatory
Global variables

Input Variables

  • I am declaring input variables. Please note that “availability zones” is a list variable containing three values.
Input Variables also know as “terraform.tfvars” file

Subnets & Zones

  • I am using the meta parameter “count”. The meta parameter is available for all resources in Terraform. In this case, I am using the “length()” function combined with the availability zone list, which equals three.
  • The built-in “element()” function is also being used to have to subnets in use a different availability zone.
  • Furthermore, I am using the “cidrsubnet()” function to calculate a CIDR block for each subnet.
Public Subnet. Each subnet in a different AZ.
Application Subnet. Each subnet in a different AZ.
Database Subnet. Each subnet in a different AZ.
Subnets created by Terraform

NAT Gateway

  • I am creating NAT Gateways in each public zone using the function “count”, “count.index”, “element()” and splat expression to reference public subnets & EIP.
Nat Gateway. It enables instances in an Application & Database subnets to connect to the Internet or other AWS services but prevent the internet from establishing connections with those instances. NAT gateway is created in each Public AZ for high availability.
Nat Gateway created by Terraform

Route Tables

  • While creating route tables, I am using splat expression to reference subnet created previously by Terraform.
  • Also, you will find an example of how “count.index” can be used for tagging resources.
Public Route Table. Route the public subnet traffic through the Internet Gateway.
Application Route Table. Create a new route table for application subnets and route traffic through the NAT Gateway into the Internet
Database Route Table. Create a new route table for database subnets and route traffic through the NAT Gateway into the Internet
Routing Tables created by Terraform

Autoscaling Group

  • In the autoscaling group configuration, I am using splat expression to reference public availability zones.
Autoscaling group. Force a redeployment when launch configuration changes and reset the desired capacity if it was changed. It set to redeploys without an outage.

Output

  • Once again, I am using splat expression to output variables as a way to organize data to be easily queried and shown back to the Terraform user.
Outputs. I am using splat expression to get resources created by Terraform.
Outputs

This video demonstrates how I deploy Terraform code. Provisioning Network Infrastructure:

To see how I just as easily destroy these resources created by Terraform:

Outcome

In this post, we saw how we could use some built-in functions in Terraform to easily make and flexibly create and scale our infrastructure, with many more tricks to help us achieve this. It is important for maintainability, infrastructure as code cleanliness, and flexibility. For the code I have demonstrated here, you can find in my GitHub repository.

Posted in Uncategorized

Getting Started with GraphQL and Spring Boot

https://www.baeldung.com/spring-graphql

1. Introduction

GraphQL is a relatively new concept from Facebook that is billed as an alternative to REST for Web APIs.

This article will give an introduction to setting up a GraphQL server using Spring Boot so that it can be added to existing applications or used in new ones.

2. What is GraphQL?

Traditional REST APIs work with the concept of Resources that the server manages. These resources can be manipulated in some standard ways, following the various HTTP verbs. This works very well as long as our API fits the resource concept, but quickly falls apart when we need to deviate from it.

This also suffers when the client needs data from multiple resources at the same time. For example, requesting a blog post and the comments. Typically this is solved by either having the client make multiple requests or by having the server supply extra data that might not always be required, leading to larger response sizes.

GraphQL offers a solution to both of these problems. It allows for the client to specify exactly what data is desired, including from navigating child resources in a single request, and allows for multiple queries in a single request.

It also works in a much more RPC manner, using named queries and mutations instead of a standard mandatory set of actions. This works to put the control where it belongs, with the API developer specifying what is possible, and the API consumer what is desired.

For example, a blog might allow the following query:

1
2
3
4
5
6
7
8
9
10
11
12
query {
    recentPosts(count: 10, offset: 0) {
        id
        title
        category
        author {
            id
            name
            thumbnail
        }
    }
}

This query will:

  • request the ten most recent posts
  • for each post, request the ID, title, and category
  • for each post request the author, returning the ID, name, and thumbnail

In a traditional REST API, this either needs 11 requests – 1 for the posts and 10 for the authors – or needs to include the author details in the post details.

2.1. GraphQL Schemas

The GraphQL server exposes a schema describing the API. This scheme is made up of type definitions. Each type has one or more fields, which each take zero or more arguments and return a specific type.

The graph is made up from the way these fields are nested with each other. Note that there is no need for the graph to be acyclic – cycles are perfectly acceptable – but it is directed. That is, the client can get from one field to its children, but it can’t automatically get back to the parent unless the schema defines this explicitly.

An example GraphQL Schema for a blog may contain the following definitions, describing a Post, an Author of the post and a root query to get the most recent posts on the blog.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type Post {
    id: ID!
    title: String!
    text: String!
    category: String
    author: Author!
}
type Author {
    id: ID!
    name: String!
    thumbnail: String
    posts: [Post]!
}
# The Root Query for the application
type Query {
    recentPosts(count: Int, offset: Int): [Post]!
}
# The Root Mutation for the application
type Mutation {
    writePost(title: String!, text: String!, category: String) : Post!
}

The “!” at the end of some names indicates that this is a non-nullable type. Any type that does not have this can be null in the response from the server. The GraphQL service handles these correctly, allowing us to request child fields of nullable types safely.

The GraphQL Service also exposes the schema itself using a standard set of fields, allowing any client to query for the schema definition ahead of time.

This can allow for the client to automatically detect when the schema changes, and to allow for clients that dynamically adapt to the way that the schema works. One incredibly useful example of this is the GraphiQL tool – discussed later – that allows for us to interact with any GraphQL API.

3. Introducing GraphQL Spring Boot Starter

The Spring Boot GraphQL Starter offers a fantastic way to get a GraphQL server running in a very short time. Combined with the GraphQL Java Tools library, we need only write the code necessary for our service.

3.1. Setting up the Service

All we need for this to work is the correct dependencies:

1
2
3
4
5
6
7
8
9
10
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java-tools</artifactId>
    <version>5.2.4</version>
</dependency>

Spring Boot will automatically pick these up and set up the appropriate handlers to work automatically.

By default, this will expose the GraphQL Service on the /graphql endpoint of our application and will accept POST requests containing the GraphQL Payload. This endpoint can be customised in our application.properties file if necessary.

3.2. Writing the Schema

The GraphQL Tools library works by processing GraphQL Schema files to build the correct structure and then wires special beans to this structure. The Spring Boot GraphQL starter automatically finds these schema files.

These files need to be saved with the extension “.graphqls” and can be present anywhere on the classpath. We can also have as many of these files as desired, so we can split the scheme up into modules as desired.

The one requirement is that there must be exactly one root query, and up to one root mutation. This can not be split across files, unlike the rest of the scheme. This is a limitation of the GraphQL Schema definition itself, and not of the Java implementation.

3.3. Root Query Resolver

The root query needs to have special beans defined in the Spring context to handle the various fields in this root query. Unlike the schema definition, there is no restriction that there only be a single Spring bean for the root query fields.

The only requirements are that the beans implement GraphQLQueryResolver and that every field in the root query from the scheme has a method in one of these classes with the same name.

1
2
3
4
5
6
public class Query implements GraphQLQueryResolver {
    private PostDao postDao;
    public List<Post> getRecentPosts(int count, int offset) {
        return postsDao.getRecentPosts(count, offset);
    }
}

The names of the method must be one of the following, in this order:

  1. <field>
  2. is<field> – only if the field is of type Boolean
  3. get<field>

The method must have parameters that correspond to any parameters in the GraphQL schema, and may optionally take a final parameter of type DataFetchingEnvironment.

The method must also return the correct return type for the type in the GraphQL scheme, as we are about to see. Any simple types – String, Int, List, etc. – can be used with the equivalent Java types, and the system just maps them automatically.

The above defined the method getRecentPosts which will be used to handle any GraphQL queries for the recentPosts field in the schema defined earlier.

3.4. Using Beans to Represent Types

Every complex type in the GraphQL server is represented by a Java bean – whether loaded from the root query or from anywhere else in the structure. The same Java class must always represent the same GraphQL type, but the name of the class is not necessary.

Fields inside the Java bean will directly map onto fields in the GraphQL response based on the name of the field.

1
2
3
4
5
6
public class Post {
    private String id;
    private String title;
    private String category;
    private String authorId;
}

Any fields or methods on the Java bean that do not map on to the GraphQL schema will be ignored, but will not cause problems. This is important for field resolvers to work.

For example, the field authorId here does not correspond to anything in our schema we defined earlier, but it will be available to use for the next step.

3.5. Field Resolvers for Complex Values

Sometimes, the value of a field is non-trivial to load. This might involve database lookups, complex calculations, or anything else. GraphQL Tools has a concept of a field resolver that is used for this purpose. These are Spring beans that can provide values in place of the data bean.

The field resolver is any bean in the Spring Context that has the same name as the data bean, with the suffix Resolver, and that implements the GraphQLResolver interface. Methods on the field resolver bean follow all of the same rules as on the data bean but are also provided the data bean itself as a first parameter.

If a field resolver and the data bean both have methods for the same GraphQL field then the field resolver will take precedence.

1
2
3
4
5
6
7
public class PostResolver implements GraphQLResolver<Post> {
    private AuthorDao authorDao;
    public Author getAuthor(Post post) {
        return authorDao.getAuthorById(post.getAuthorId());
    }
}

The fact that these field resolvers are loaded from the Spring context is important. This allows them to work with any other Spring managed beans – e.g., DAOs.

Importantly, if the client does not request a field, then the GraphQL Server will never do the work to retrieve it. This means that if a client retrieves a Post and does not ask for the Author, then the getAuthor()method above will never be executed, and the DAO call will never be made.

3.6. Nullable Values

The GraphQL Schema has the concept that some types are nullable and others are not.

This can be handled in the Java code by directly using null values, but equally, the new Optional type from Java 8 can be used directly here for nullable types, and the system will do the correct thing with the values.

This is very useful as it means that our Java code is more obviously the same as the GraphQL schema from the method definitions.

3.7. Mutations

So far, everything that we have done has been about retrieving data from the server. GraphQL also has the ability to update the data stored on the server, by means of mutations.

From the point of view of the code, there is no reason that a Query can’t change data on the server. We could easily write query resolvers that accept arguments, save new data and return those changes. Doing this will cause surprising side effects for the API clients, and is considered bad practice.

Instead, Mutations should be used to inform the client that this will cause a change to the data being stored.

Mutations are defined in the Java code by using classes that implement GraphQLMutationResolver instead of GraphQLQueryResolver.

Otherwise, all of the same rules apply as for queries. The return value from a Mutation field is then treated exactly the same as from a Query field, allowing nested values to be retrieved as well.

1
2
3
4
5
6
7
public class Mutation implements GraphQLMutationResolver {
    private PostDao postDao;
    public Post writePost(String title, String text, String category) {
        return postDao.savePost(title, text, category);
    }
}

4. Introducing GraphiQL

GraphQL also has a companion tool called GraphiQL. This is a UI that is able to communicate with any GraphQL Server and execute queries and mutations against it. A downloadable version of it exists as an Electron app and can be retrieved from here.

It is also possible to include the web-based version of GraphiQL in our application automatically, by adding the GraphiQL Spring Boot Starter dependency:

1
2
3
4
5
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphiql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>

This will only work if we are hosting our GraphQL API on the default endpoint of /graphql though, so the standalone application will be needed if that is not the case.

5. Summary

GraphQL is a very exciting new technology that can potentially revolutionize the way that Web APIs are developed.

The combination of the Spring Boot GraphQL Starter and the GraphQL Java Tools libraries make it incredibly easy to add this technology to any new or existing Spring Boot applications.

Code snippets can be found over on GitHub.

Posted in Uncategorized

Spring Scope

source: https://www.baeldung.com/spring-bean-scopes

1. Overview

In this quick tutorial, you’ll learn about the different types of bean scopes in the Spring framework.

The scope of a bean defines the life cycle and visibility of that bean in the contexts in which it is used.

The latest version of Spring framework defines 6 types of scopes:

  • singleton
  • prototype
  • request
  • session
  • application
  • websocket

The last four scopes mentioned request, session, application and websocket are only available in a web-aware application.

2. Singleton Scope

Defining a bean with singleton scope means the container creates a single instance of that bean, and all requests for that bean name will return the same object, which is cached. Any modifications to the object will be reflected in all references to the bean. This scope is the default value if no other scope is specified.

Let’s create a Person entity to exemplify the concept of scopes:

1
2
3
4
5
public class Person {
    private String name;
    // standard constructor, getters and setters
}

Afterwards, we define the bean with singleton scope by using the @Scope annotation:

1
2
3
4
5
@Bean
@Scope("singleton")
public Person personSingleton() {
    return new Person();
}

We can also use a constant instead of the String value in the following manner:

1
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)

Now we proceed to write a test that shows that two objects referring to the same bean will have the same values, even if only one of them changes their state, as they are both referencing the same bean instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static final String NAME = "John Smith";
@Test
public void givenSingletonScope_whenSetName_thenEqualNames() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scopes.xml");
    Person personSingletonA = (Person) applicationContext.getBean("personSingleton");
    Person personSingletonB = (Person) applicationContext.getBean("personSingleton");
    personSingletonA.setName(NAME);
    Assert.assertEquals(NAME, personSingletonB.getName());
    ((AbstractApplicationContext) applicationContext).close();
}

The scopes.xml file in this example should contain the xml definitions of the beans used:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    <bean id="personSingleton" class="org.baeldung.scopes.Person" scope="singleton"/>   
</beans>

3. Prototype Scope

A bean with prototype scope will return a different instance every time it is requested from the container. It is defined by setting the value prototype to the @Scope annotation in the bean definition:

1
2
3
4
5
@Bean
@Scope("prototype")
public Person personPrototype() {
    return new Person();
}

We could also use a constant as we did for the singleton scope:

1
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

We will now write a similar test as before that shows two objects requesting the same bean name with scope prototype will have different states, as they are no longer referring to the same bean instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static final String NAME = "John Smith";
private static final String NAME_OTHER = "Anna Jones";
@Test
public void givenPrototypeScope_whenSetNames_thenDifferentNames() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scopes.xml");
    Person personPrototypeA = (Person) applicationContext.getBean("personPrototype");
    Person personPrototypeB = (Person) applicationContext.getBean("personPrototype");
    personPrototypeA.setName(NAME);
    personPrototypeB.setName(NAME_OTHER);
    Assert.assertEquals(NAME, personPrototypeA.getName());
    Assert.assertEquals(NAME_OTHER, personPrototypeB.getName());
    ((AbstractApplicationContext) applicationContext).close();
}

The scopes.xml file is similar to the one presented in the previous section while adding the xml definition for the bean with prototype scope:

1
<bean id="personPrototype" class="org.baeldung.scopes.Person" scope="prototype"/>

4. Web Aware Scopes

As mentioned, there are four additional scopes that are only available in a web-aware application context. These are less often used in practice.

The request scope creates a bean instance for a single HTTP request while session scope creates for an HTTP Session.

The application scope creates the bean instance for the lifecycle a ServletContext and the websocket scope creates it for a particular WebSocket session.

Let’s create a class to use for instantiating the beans:

1
2
3
4
5
public class HelloMessageGenerator {
    private String message;
    
    // standard getter and setter
}

4.1. Request Scope

We can define the bean with request scope using the @Scope annotation:

1
2
3
4
5
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator requestScopedBean() {
    return new HelloMessageGenerator();
}

The proxyMode attribute is necessary because, at the moment of the instantiation of the web application context, there is no active request. Spring will create a proxy to be injected as a dependency, and instantiate the target bean when it is needed in a request.

Next, we can define a controller that has an injected reference to the requestScopedBean. We need to access the same request twice in order to test the web specific scopes.

If we display the message each time the request is run, we can see that the value is reset to null, even though it is later changed in the method. This is because of a different bean instance being returned for each request.

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class ScopesController {
    @Resource(name = "requestScopedBean")
    HelloMessageGenerator requestScopedBean;
    @RequestMapping("/scopes/request")
    public String getRequestScopeMessage(final Model model) {
        model.addAttribute("previousMessage", requestScopedBean.getMessage());
        requestScopedBean.setMessage("Good morning!");
        model.addAttribute("currentMessage", requestScopedBean.getMessage());
        return "scopesExample";
    }
}

4.2. Session Scope

We can define the bean with session scope in a similar manner:

1
2
3
4
5
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator sessionScopedBean() {
    return new HelloMessageGenerator();
}

Next, we define a controller with a reference to the sessionScopedBean. Again, we need to run two requests in order to show that the value of the message field is the same for the session.

In this case, when the request is made for the first time, the value message is null. But once, it is changed, then that value is retained for subsequent requests as the same instance of the bean is returned for the entire session.

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class ScopesController {
    @Resource(name = "sessionScopedBean")
    HelloMessageGenerator sessionScopedBean;
    @RequestMapping("/scopes/session")
    public String getSessionScopeMessage(final Model model) {
        model.addAttribute("previousMessage", sessionScopedBean.getMessage());
        sessionScopedBean.setMessage("Good afternoon!");
        model.addAttribute("currentMessage", sessionScopedBean.getMessage());
        return "scopesExample";
    }
}

4.3. Application Scope

The application scope creates the bean instance for the lifecycle of a ServletContext.

This is similar to the singleton scope but there is a very important difference with regards to the scope of the bean.

When beans are application scoped the same instance of the bean is shared across multiple servlet-based applications running in the same ServletContext, while singleton-scoped beans are scoped to a single application context only.

Let’s create the bean with application scope:

1
2
3
4
5
@Bean
@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator applicationScopedBean() {
    return new HelloMessageGenerator();
}

And the controller that references this bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class ScopesController {
    @Resource(name = "applicationScopedBean")
    HelloMessageGenerator applicationScopedBean;
    @RequestMapping("/scopes/application")
    public String getApplicationScopeMessage(final Model model) {
        model.addAttribute("previousMessage", applicationScopedBean.getMessage());
        applicationScopedBean.setMessage("Good afternoon!");
        model.addAttribute("currentMessage", applicationScopedBean.getMessage());
        return "scopesExample";
    }
}

In this case, value message once set in the applicationScopedBean will be retained for all subsequent requests, sessions and even for a different servlet application that will access this bean, provided it is running in the same ServletContext.

4.4. WebSocket Scope

Finally, let’s create the bean with websocket scope:

1
2
3
4
5
@Bean
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator websocketScopedBean() {
    return new HelloMessageGenerator();
}

WebSocket-scoped beans when first accessed are stored in the WebSocket session attributes. The same instance of the bean is then returned whenever that bean is accessed during the entire WebSocket session.

We can also say that it exhibits singleton behavior but limited to a WebSocket session only.

5. Conclusion

We have demonstrated different bean scopes provided by Spring and what their intended usages are.

The implementation of this tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

Posted in Uncategorized

Spring bean thread safety guide

source: http://dolszewski.com/spring/spring-bean-thread-safety-guide/

Is Spring controller/service/singleton thread-safe?

It’s a commonly asked question by Spring newcomers and probably a must-have warm-up question on job interviews. As usual in programming, the answer is: it depends. The main factor which determines thread safety of a component is its scope.

Let’s get down to it and see what Spring’s scopes have to offer in multithreaded programming.

Which Spring scope is thread-safe?

In order to answer that question, you first need to understand when Spring creates a new thread.

In a standard servlet-based Spring web application, every new HTTP request generates a new thread. If the container creates a new bean instance just for that particular request, we can say this bean is thread-safe.

Let’s examine what scopes we have in Spring and focus on when the container creates them.

Is Spring singleton thread safe?

The short answer is: no, it isn’t.

And you probably already know why.

It’s because of the long life cycle of singleton beans. Those beans may be reused over and over again in many HTTP requests coming from different users.

If you don’t use @Lazy, the framework creates a singleton bean at the application startup and makes sure that the same instance is autowired and reused in all other dependent beans. As long the container lives, the singleton beans live as well.

But the framework doesn’t control how the singleton is used. If two different threads execute a method of the singleton at the same time, you’re not guaranteed that both calls will be synchronized and run in the sequence.

In other words, it’s your responsibility to ensure your code runs safely in the multithreaded environment. Spring won’t do that for you.

Request scope to the rescue

If you want to make sure your bean is thread-safe, you should go for the @RequestScopeAs the name suggests, Spring binds such bean to a particular web request. Request beans aren’t shared between multiple threads, hence you don’t have to care about concurrency.

But hang on a minute.

If request scope beans are so great when it comes to concurrency, maybe we should use the scope for all application beans? Before you set the request scope to all your components,  ask yourself the following question.

Do you really need all your beans to be thread-safe?

Usually, you don’t.

Creating a new instance of a bean instead of reusing the existing one is always slower. Stick to singletons unless you have a real use case for request scope beans.

Problematic session scope

Spring associates session beans with a particular user. When a new user visits your application, a new session bean instance is created and reused for all requests from that user.

As you know, some user’s requests may be concurrent. Because of that fact, session beans aren’t thread-safe. Their life cycle is longer than request scope beans. Multiple requests may call the same session bean concurrently.

Tricky thread safety with prototype beans

I left the prototype scope as the last one to discuss because we can’t clearly say it’s always thread-safe or not. Prototype’s thread safety depends on the scope of the bean which contains the prototype.

Spring creates a prototype bean on demand whenever another bean requires its instance.

Imagine you have two beans in your application. One is the singleton and the second is the request scoped component. Both depend on a third bean which is the prototype.

Let’s consider the singleton bean first. Because the singleton isn’t thread-safe, calls to its prototype methods may also run concurrently. When several threads share the singleton, the single instance of the prototype that Spring injects to that singleton will also be shared.

It works the same for all other scopes which make a bean reusable in several web requests.

Prototype in Singleton

What about the request scope bean? Spring creates a new instance of such component for each web request. Each request is bound to a separate thread. Therefore, each instance of the request bean gets its own instance of the prototype bean. In that case, you can consider the prototype as thread-safe.

Request bean in Singleton

So are Spring web controllers thread-safe or not?

The answer again is: it depends.

It depends on the scope of such a controller.

If you define a controller as the default singleton bean, it won’t be thread-safe. Changing the default scope to the session won’t make the controller safe either. However, the request scope will make the controller bean safe to work for concurrent web requests.

What about controllers with the prototype scope? You already know its thread safety depends on the scope of the bean which contains the prototype as a dependency. But we never inject controllers to other beans, right? They’re entry points to our application. So how does Spring behave when you define a controller as the prototype bean?

As you probably suppose, when you define a controller as the prototype, the Spring framework will create a new instance for each web request it serves. Unless you inject them to unsafe scoped beans, you can consider prototype scoped controllers as thread-safe.

How to make any Spring bean thread-safe?

The best thing you can do to tackle access synchronization is to avoid it.

How?

By making your bean classes stateless.

The bean is stateless if execution of its methods doesn’t modify its instance fields. Changing local variables inside a method is totally fine because each call to a method allocates the memory for these variables. Unlike instance fields which are shared between all non-static methods.

The perfect stateless bean has no fields but you won’t see such utility classes very often. Usually, your beans have some fields. But by applying a few simple rules, you can make any bean stateless and thread-safe.

How to make Spring bean stateless?

Start by making all bean fields final to indicate that during the life cycle of the bean fields shouldn’t be reassigned again.

CODE

But don’t confuse field modification with reassignment! Making all bean’s fields final doesn’t make it stateless. If values you assigned to final fields of a bean can be changed during the runtime, such bean is still not thread-safe.

The above example presents a stateless bean because you can’t change the value of the String field. The String class is immutable just like Integer, Boolean, and other primitive wrappers. You can also use primitive types safely in this case. But what about more complex objects like standard Lists, Maps, or your custom data classes?

For the common types like collections, you can go for immutable implementations which you can find in the standard Java library. You can easily create immutable collections with factory methods added in Java 9. If you still use an older version, don’t worry. You can also find conversion methods like unmodifiableList() in the Collections class.

If it comes to custom data types, you have to make sure they are immutable on your own. Creating an immutable class in Java goes beyond the scope of this article. If you need a more detailed guide, read how to design immutable classes in the official Java documentation.

Sounds easy enough. But some of your beans may maintain some state. What then?

Thread-safe variable in stateful Spring bean

Stateless bean sounds like the silver bullet. But what if you already have a stateful bean and you must synchronize access on one of its fields?

In that case, you have the classic Java problem with the concurrent modification access to a class field. The Spring framework won’t solve it for you. You need to select one of the possible solutions:

  • The synchronized keyword and Locks – This option gives you the most control over access synchronization but also requires a deeper understanding of mechanisms used in the concurrent environment.
  • Atomic variables – You can find a small set of thread-safe types in the Java standard library. Types from that package can be safely used as fields in shared stateful beans.
  • Concurrent collections – In addition to atomic variables, Java provides us with a few useful collections which we can use without worrying about the concurrent access problem.

But beware: no matter which method you choose, access synchronization always has an impact on the performance. Try to avoid it if you have an alternative option.

Implementing thread-safe method in Spring component

Frankly, I’ve never had such case in any of my commercial projects but I was asked that question on an interview some time ago so you also may hear it.

As we already discussed, Spring itself doesn’t solve the problem of the concurrent access. If the scope of your bean isn’t thread-safe but its method contains some critical code that you always want to run safely, use the synchronized keyword on that method.

Conclusion

At this point, you should know the position of the Spring framework in the multithreaded environment. You learned how the scope of a component affects its safety and what are the options when you have to provide thread safety on your own.

If you like the post, subscribe to my blog so you won’t miss the next article. Also please leave a comment if you have some interesting stories about tackling concurrency problems in Spring applications. I would love to read them.