Enhance Spring Boot APIs with Custom @RequestParam Wrappers
Enhance Spring Boot APIs with Custom @RequestParam Wrappers

Convert @RequestParam Map to Custom Wrapper Object in Spring Boot

Learn how converting @RequestParam Map into a custom wrapper object optimizes readability & flexibility in Spring Boot APIs.6 min


Working with parameters in Spring Boot APIs often involves simple usage of the @RequestParam annotations. Typically, you might receive these as a Map. This approach works conveniently, but once you start building more sophisticated APIs with numerous parameters and custom logic, things can quickly get cluttered.

That’s where converting the traditional @RequestParam Map into a custom wrapper object becomes incredibly useful. It helps to enhance readability, maintainability, and flexibility. Let’s explore how this works practically in Spring Boot.

Utilizing @RequestParam Map<String, String> in Spring Boot

When you build RESTful web services with Spring Boot, one of the easiest ways to capture URL parameters is by using @RequestParam with a Map. It collects all incoming request parameters as key-value pairs.

Here’s a quick example:

@GetMapping("/search")
public ResponseEntity<String> search(@RequestParam Map<String, String> params) {
    String keyword = params.get("keyword");
    String page = params.get("page");
    // processing logic...
    return ResponseEntity.ok("Search Results");
}

This technique is simple and practical. There’s no need to define each parameter explicitly. The map conveniently captures all parameters, allowing easy access via the parameter names as keys.

However, this simplicity has limitations once you start working with complex business logic and handling validations, defaults, or processing many parameters thoughtfully becomes tedious.

Creating a Custom Wrapper Object for Request Params

Instead of using a generic map throughout your controllers, you can encapsulate request parameters into a custom wrapper class—we’ll call it RequestMap. This wrapper lets you add handy methods for quick retrieval, validation, and parsing of the parameters directly within the request handling.

Here’s how a basic implementation of RequestMap might look:

public class RequestMap {
    private Map<String, String> params;

    public RequestMap(Map<String, String> params) {
        this.params = params;
    }

    public String getString(String key) {
        return params.get(key);
    }

    public int getInt(String key, int defaultValue) {
        try {
            return Integer.parseInt(params.get(key));
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    public boolean contains(String key) {
        return params.containsKey(key);
    }

    // Other utility methods as needed...
}

By using such a wrapper class, you get the benefit of simplifying repetitive tasks like casting strings to integers or booleans, checking parameter existence, and managing default values in a cleaner, reusable way.

Implementing Automatic Conversion of Map to Custom Wrapper Object

Although defining your parameters using POJOs (Plain Old Java Objects) can also be useful, sometimes your API may require dynamic parameters or a more generic approach. In these scenarios, automatically converting a Map into your wrapper is highly beneficial.

The ultimate goal isn’t merely creating another object, but seamlessly injecting your wrapper class directly into your Spring controller methods. Spring’s @ModelAttribute annotation along with a custom constructor makes it easy to bind request params directly to your custom wrapper.

Step-by-Step Guide to Achieving Automatic Conversion

To implement automatic conversion from a request parameter Map into a custom wrapper, you’ll follow these two straightforward steps:

1. Adjust your custom RequestMap class:
Add a constructor accepting Map to allow automatic binding by Spring.

public class RequestMap {
    private Map<String, String> params;

    public RequestMap(@RequestParam Map<String, String> params) {
        this.params = params;
    }

    // methods as earlier mentioned
}

2. Modify your controller method signature:
Change your controller’s method parameter type from a Map to your custom wrapper class.

@GetMapping("/search")
public ResponseEntity<String> search(@ModelAttribute RequestMap params) {
    String keyword = params.getString("keyword");
    int page = params.getInt("page", 1); // Default to page 1 if missing
    // process the parameters accordingly
    return ResponseEntity.ok("Results for " + keyword + " at page " + page);
}

Spring automatically handles the map injection to your constructor thanks to the @ModelAttribute binding mechanism.

Benefits of Using a Custom Wrapper Over Map

Switching from raw Maps to our custom wrapper object provides several major advantages:

  • Improved Readability and Maintainability: Your controller methods become clearer and leaner. Instead of manual casting repeatedly, you have concise and expressive methods like params.getInt(“field”).
  • Enhanced Flexibility and Extensibility: Need to add specific parsing, apply defaults, or validate inputs? Just enhance your wrapper methods. Each new component inherits that convenience instantly.
  • Simplified Validation and Error Handling: Centralized error handling and default value setup are easier inside your wrapper. You avoid cluttering controllers with repetitive boilerplate.

Demonstration of the Custom Wrapper Object in Action

Consider this situation before and after implementing our custom wrapper. Previously, you had to manually process parameters:

// Old style with @RequestParam Map
@GetMapping("/products")
public ResponseEntity<String> products(@RequestParam Map<String, String> params) {
    String category = params.get("category");
    int limit = 10;
    if(params.containsKey("limit")) {
        try {
            limit = Integer.parseInt(params.get("limit"));
        } catch (NumberFormatException ignored) {}
    }
    // Further processing...
}

Now compare it with the cleaner, enhanced version using your custom wrapper:

// Improved style with RequestMap wrapper
@GetMapping("/products")
public ResponseEntity<String> products(@ModelAttribute RequestMap params) {
    String category = params.getString("category");
    int limit = params.getInt("limit", 10);
    // Further processing cleanly...
}

Clearly, the wrapper approach is simpler, cleaner, easier to maintain, and scales efficiently in larger projects.

Explore Further Customization and Optimization Opportunities

Moving from basic request parameter handling towards custom wrapper objects improves your Spring Boot applications dramatically in terms of code quality, maintainability, and readability. But don’t stop there!

Explore additional Spring functionalities such as custom type converters, validators, and using DTOs effectively. Your application might also benefit from integrating frameworks like Hibernate Validator or employing modern data-handling practices documented in the JavaScript ecosystem.

Adopting cleaner coding patterns not only improves your developers’ experiences but significantly reduces ongoing maintenance overhead. So, why not start optimizing your Spring Boot apps right now?


Like it? Share with your friends!

Shivateja Keerthi
Hey there! I'm Shivateja Keerthi, a full-stack developer who loves diving deep into code, fixing tricky bugs, and figuring out why things break. I mainly work with JavaScript and Python, and I enjoy sharing everything I learn - especially about debugging, troubleshooting errors, and making development smoother. If you've ever struggled with weird bugs or just want to get better at coding, you're in the right place. Through my blog, I share tips, solutions, and insights to help you code smarter and debug faster. Let’s make coding less frustrating and more fun! My LinkedIn Follow Me on X

0 Comments

Your email address will not be published. Required fields are marked *