eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

1. Overview

There are many web frameworks like SpringPlay, and Grails available in the Java ecosystem. However, none of them can claim to be completely immutable and object-oriented.

In this tutorial, we’ll explore the Takes framework and create a simple web application using its common features like routing, request/response handling, and unit testing.

2. Takes

Takes is an immutable Java 8 web framework that neither uses null nor public static methods.

Also, the framework doesn’t support mutable classes, casting, or reflection. Hence, it is a true object-oriented framework.

Takes don’t require configuration files for the setup. Besides that, it provides built-in features like JSON/XML response and templating.

3. Setup

First, we’ll add the latest takes Maven dependency to the pom.xml:

<dependency>
    <groupId>org.takes</groupId>
    <artifactId>takes</artifactId>
    <version>1.19</version>
</dependency>

Then, let’s create the TakesHelloWorld class that implements the Take interface:

public class TakesHelloWorld implements Take {
    @Override
    public Response act(Request req) {
        return new RsText("Hello, world!");
    }
}

The Take interface provides the fundamental feature of the framework. Each Take serves as a request handler, returning the response through the act method.

Here, we’ve used the RsText class to render the plain text Hello, world! as a response, when a request is made to the TakesHelloWorld take.

Next, we’ll create the TakesApp class to start the web application:

public class TakesApp {
    public static void main(String... args) {
        new FtBasic(new TakesHelloWorld()).start(Exit.NEVER);
    }
}

Here, we’ve used the FtBasic class that provides the basic implementation of the Front interface to start the webserver and forward the request to the TakesHelloWorld take.

Takes implements its own stateless webserver by using the ServerSocket class. By default, it starts the server on port 80. However, we can define the port in the code:

new FtBasic(new TakesHelloWorld(), 6060).start(Exit.NEVER);

Or, we can pass the port number using the command-line parameter –port.

Then, let’s compile the classes using the Maven command:

mvn clean package

Now, we’re ready to run the TakesApp class as a simple Java application in an IDE.

4. Run

We can also run our TakesApp class as a separate web server application.

4.1. Java Command Line

First, let’s compile our classes:

javac -cp "takes.jar:." com.baeldung.takes.*

Then, we can run the application using the Java command line:

java -cp "takes.jar:." com.baeldung.takes.TakesApp --port=6060

4.2. Maven

Or, we can use the exec-maven-plugin plugin to run it through Maven:

<profiles>
    <profile>
        <id>reload</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>3.1.0</version>
                    <executions>
                        <execution>
                            <id>start-server</id>
                            <phase>pre-integration-test</phase>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <mainClass>com.baeldung.takes.TakesApp</mainClass>
                        <cleanupDaemonThreads>false</cleanupDaemonThreads>
                        <arguments>
                            <argument>--port=${port}</argument>
                        </arguments>
                   </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Now, we can run our app using the Maven command:

mvn clean integration-test -Preload -Dport=6060

5. Routing

The framework provides the TkFork class to route the requests to different takes.

For instance, let’s add a few routes to our application:

public static void main(String... args) {
    new FtBasic(
        new TkFork(
            new FkRegex("/", new TakesHelloWorld()),
            new FkRegex("/contact", new TakesContact())
        ), 6060
    ).start(Exit.NEVER);
}

Here, we’ve used the FkRegex class to match the request path.

6. Request Handling

The framework provides a few decorator classes in the org.takes.rq package to handle the HTTP request.

For example, we can use the RqMethod interface to extract the HTTP method:

public class TakesHelloWorld implements Take { 
    @Override
    public Response act(Request req) throws IOException {
        String requestMethod = new RqMethod.Base(req).method(); 
        return new RsText("Hello, world!"); 
    }
}

Similarly, the RqHeaders interface is available to fetch the request headers:

Iterable<String> requestHeaders = new RqHeaders.Base(req).head();

We can use the RqPrint class to get the body of the request:

String body = new RqPrint(req).printBody();

Likewise, we can use the RqFormSmart class to access the form parameter:

String username = new RqFormSmart(req).single("username");

7. Response Handling

Takes also provides many useful decorators to handle the HTTP response in the org.takes.rs package.

The response decorator implements the head and body methods of the Response interface.

For instance, the RsWithStatus class renders the response with status code:

Response resp = new RsWithStatus(200);

The output of the response can be verified using the head method:

assertEquals("[HTTP/1.1 200 OK], ", resp.head().toString());

Similarly, the RsWithType class renders the response with content-type:

Response resp = new RsWithType(new RsEmpty(), "text/html");

Here, the RsEmpty class renders the empty response.

Likewise, we can use the RsWithBody class to render the response with the body.

So, let’s create the TakesContact class and use the discussed decorators to render the response:

public class TakesContact implements Take {
    @Override
    public Response act(Request req) throws IOException {
        return new RsWithStatus(
          new RsWithType(
            new RsWithBody("Contact us at https://www.baeldung.com"), 
            "text/html"), 200);
    }
}

Similarly, we can use the RsJson class to render the JSON response:

@Override 
public Response act(Request req) { 
    JsonStructure json = Json.createObjectBuilder() 
      .add("id", rs.getInt("id")) 
      .add("user", rs.getString("user")) 
      .build(); 
    return new RsJson(json); 
}

8. Exception Handling

The framework contains the Fallback interface to handle exceptional conditions. It also provides a few implementations to handle the fallback scenarios.

For instance, let’s use the TkFallback class to handle the HTTP 404 and shows a message to the user:

public static void main(String... args) throws IOException, SQLException {
    new FtBasic(
        new TkFallback(
          new TkFork(
            new FkRegex("/", new TakesHelloWorld()),
            // ...
            ),
            new FbStatus(404, new RsText("Page Not Found"))), 6060
     ).start(Exit.NEVER);
}

Here, we’ve used the FbStatus class to handle the fallback on the defined status code.

Similarly, we can use the FbChain class to define a combination of fallbacks:

new TkFallback(
    new TkFork(
      // ...
      ),
    new FbChain(
      new FbStatus(404, new RsText("Page Not Found")),
      new FbStatus(405, new RsText("Method Not Allowed"))
      )
    ), 6060
).start(Exit.NEVER);

Also, we can implement the Fallback interface to handle the exceptions:

new FbChain(
    new FbStatus(404, new RsText("Page Not Found")),
    new FbStatus(405, new RsText("Method Not Allowed")),
    new Fallback() {
        @Override
        public Opt<Response> route(RqFallback req) {
          return new Opt.Single<Response>(new RsText(req.throwable().getMessage()));
        }
    }
)

9. Templates

Let’s integrate Apache Velocity with our Takes web app to provide some templating functionality.

First, we’ll add the velocity-engine-core Maven dependency:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>

Then, we’ll use the RsVelocity class to define the template string and the binding parameters in the act method:

public class TakesIndex implements Take {
    @Override
    public Response act(Request req) throws IOException {
        return new RsHtml(
            new RsVelocity("${username}", new RsVelocity.Pair("username", "Baeldung")));
        );
    }
}

Here, we’ve used the RsHtml class to render the HTML response.

Also, we can use a velocity template with the RsVelocity class:

new RsVelocity(this.getClass().getResource("/templates/index.vm"), 
    new RsVelocity.Pair("username", username))
);

10. Unit Testing

The framework supports unit testing of any Take by providing the RqFake class that creates a fake request:

For example, let’s write a unit test for our TakesContact class using JUnit:

String resp = new RsPrint(new TakesContact().act(new RqFake())).printBody();
assertEquals("Contact us at https://www.baeldung.com", resp);

11. Integration Testing

We can test the entire application using JUnit and any HTTP client.

The framework provides the FtRemote class that starts the server on the random port and provides remote control to the execution of the Take.

For instance, let’s write an integration test and verify the response of the TakesContact class:

new FtRemote(new TakesContact()).exec(
    new FtRemote.Script() {
        @Override
        public void exec(URI home) throws IOException {
            HttpClient client = HttpClientBuilder.create().build();    
            HttpResponse response = client.execute(new HttpGet(home));
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            
            assertEquals(200, statusCode);
            assertEquals("Contact us at https://www.baeldung.com", result);
        }
    });

Here, we’ve used Apache HttpClient to make the requests to the server and verify the response.

12. Conclusion

In this tutorial, we’ve explored the Takes framework by creating a simple web application.

First, we’ve seen a quick way to set up the framework in our Maven project and run our application.

Then, we examined a few common features like routing, request/response handling, and unit testing.

Lastly, we explored the support of unit and integration testing provided by the framework.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (All)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – LS – NPI (cat=REST)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)