DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Dependency Injection in Spring
  • Filtering Java Collections via Annotation-Driven Introspection
  • Spring Microservice Application Resilience: The Role of @Transactional in Preventing Connection Leaks
  • Mastering Spring: Synchronizing @Transactional and @Async Annotations With Various Propagation Strategies

Trending

  • Agentic AI for Automated Application Security and Vulnerability Management
  • Ethical AI in Agile
  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  1. DZone
  2. Coding
  3. Languages
  4. Spring Web Service Response Filtering

Spring Web Service Response Filtering

For large projects, you must control the serialization of a service response.

By 
Ruslan Konovalov user avatar
Ruslan Konovalov
·
Updated Nov. 29, 18 · Tutorial
Likes (12)
Comment
Save
Tweet
Share
57.4K Views

Join the DZone community and get the full member experience.

Join For Free

Image title

Introduction

Sometimes, mostly in large projects, there is a need to control the serialization of a service response — especially to filter fields of an object in response. For solving this type of issue, we have several solutions. Let’s take a look.

Issue

For example, we have an object named “User” that contains fields like: id, email, fullName, password, secretKey. We have a task to return this object to a recipient with different fields depending on the role in the session. Also, we have two types of roles: admin and user:

  1. When the recipient has an “admin” role, we should return the full object with the fields: id, email, fullName, password, secretKey.
  2. When a recipient has a “user” role, we should return an object partially with the fields: email, fullName.

Standard Solutions

  1. Inherit two different classes with a different set of fields from the User class and call them like: UserAdmin, UserSimple.
  2. Reset fields of the User class in response to the method depending on the role.
  3. Then, return the recipient to a serialized string with removed fields depending on role instead of User class.

Maybe this solution looks simple and justified, but it is not the best. In some situations, it will increase the number of similar classes or will lead to unpredictability of the service execution. But in all solutions, we need to create additional logic code.

JFilter Solution

This approach offers another solution. We can leave the service’s method response unchanged. But we need to somehow get the Spring message converter work. To let him know how to serialize an object and filter/exclude fields, the JFilter module is designed to solve this kind of issue.

Let’s look at the diagram.

The diagram of module flowchart

As you can see, the JFilter module is embedded between Spring Web Service and Send response methods. The description of internal parts of the module include:

  1.  FilterAdvice— is a ControllerAdvice component that handles all responses from the Spring Web Service
  2.  FilterProvider — is a component that attempts to find a suitable filter
  3.  FilterConverter — is a class that attempts to provide a suitable JSON or XML serializer
  4. After serialization, the response will be written to the HttpOutputMessage body

Using

Before discussing filter types, we should know how to use them in your project. So, first of all, we need to import the repository:

<dependency>
    <groupId>com.github.rkonovalov</groupId>
    <artifactId>json-ignore</artifactId>
    <version>1.0.8</version>
</dependency>


If you are using other automation tools, you can find a declaration by following this link.

The next step is enabling filter handling:

@ComponentScan({"com.jfilter.components"})
@EnableJsonFilter


This annotation should be declared in the Spring Web Service configuration component. The following code shows you how you can declare it:

@Configuration
@EnableWebMvc
@ComponentScan({"com.jfilter.components"})
@EnableJsonFilter
public class AppConfig extends WebMvcConfigurerAdapter {

}


After these two simple steps, we can start to explore filter types. But before that, we also need to define a sample Spring Rest component with the response method:

@RestController
public class SessionService {
    @Autowired
    private UserController userController;   

    @RequestMapping(value = "/users/signIn",
            params = {"email", "password"}, method = RequestMethod.POST,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
            produces = {MediaType.APPLICATION_JSON_VALUE})            
    public User signIn(@RequestParam("email") String email, @RequestParam("password") String password) {
        return userController.signInUser(email, password);
    }
}


This method returns the object instance of the User class. There is a JSON serialized object that will be sent to the recipient.

{
  "id": 10,
  "email": "janedoe@gmail.com", 
  "fullName": "Jane Doe",
  "password": "12345",
  "secretKey": "54321",
  "address": {
    "id": 15,
    "apartmentNumber": 22,
    "street": {
      "id": 155,
      "streetName": "Bourbon Street",
      "streetNumber": 15
    }
  }
}


That’s it. Now, we can declare the filter annotations.

Filters

Filters mainly analyze the Spring Service response for a filter annotation, and if the annotation is configured, it attempts to generate a list of filterable/exclusion fields from the response object. Let’s look at them a little closer.

Field Filter

This is a simple filter annotation where you can to define filterable fields of an object.

Annotation Example

@FieldFilterSetting(className = User.class, fields = {"id", "password", "secretKey"})


Code Example

@FieldFilterSetting(className = User.class, fields = {"id", "password", "secretKey"})
    @RequestMapping(value = "/users/signIn",
            params = {"email", "password"}, method = RequestMethod.POST,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
            produces = {MediaType.APPLICATION_JSON_VALUE})            
    public User signIn(@RequestParam("email") String email, @RequestParam("password") String password) {
        return userController.signInUser(email, password);
    }


Response Result

{ 
  "email": "janedoe@gmail.com", 
  "fullName": "Jane Doe",
  "address": {
    "id": 15,
    "apartmentNumber": 22,
    "street": {
      "id": 155,
      "streetName": "Bourbon Street",
      "streetNumber": 15
    }
  }
}


As you can see, fields id, password, and secretKey have been successfully filtered from the response.

If you want to filter fields from a complex class that contains sub-classes with the same field names, you can filter them without qualifications for a certain class name.

Annotation Example

@FieldFilterSetting(fields = {"id", "password", "secretKey"})


Response Result

{ 
  "email": "janedoe@gmail.com", 
  "fullName": "Jane Doe",
  "address": {
    "apartmentNumber": 22,
    "street": {
      "streetName": "Bourbon Street",
      "streetNumber": 15
    }
  }
}


As you can see, all id fields from all sub-objects have been filtered. Also, you can filter fields from sub-objects separately.

Annotation Example

@FieldFilterSetting(className = User.class, fields = {"id", "password", "secretKey"})
@FieldFilterSetting(className = Address.class, fields = {"apartmentNumber"})
@FieldFilterSetting(className = Street.class, fields = {"streetNumber"})


Response Result

{
  "email": "janedoe@gmail.com", 
  "fullName": "Jane Doe",
  "address": {
    "id": 15,
    "street": {
      "id": 155,
      "streetName": "Bourbon Street"
    }
  }
}


Session Strategy Filter

Sometimes, you need to filter fields depending on the recipient role (attribute in HTTP Session). As an example, you have two recipient roles: ADMIN and USER

USER Role Annotation Example

@SessionStrategy(attributeName = "ROLE", attributeValue = "USER", ignoreFields = {
            @FieldFilterSetting(className = User.class, fields = {"id", "password"})
    })


ADMIN Role Annotation Example

@SessionStrategy(attributeName = "ROLE", attributeValue = "ADMIN", ignoreFields = {
                @FieldFilterSetting(className = User.class, fields = {"id"})
    })


So, if the session has an attribute ROLE with value:

  1. USER — fields id, password will be removed from the response
  2. ADMIN — the field idwill be removed from the response

Thus, this filter gives flexibility and the possibility of selective filtering.

XML Schema-Based Filter

If you need to configure field filtration in a file, this filter can provide this feature.

Annotation Example

@FileFilterSetting(fileName = "filter_configuration.xml")


XML Configuration File

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE config PUBLIC
        "-//json/json-ignore mapping DTD 1.0//EN"
        "https://rkonovalov.github.io/json-ignore-schema-1.0.dtd">
<config>
    <controller class-name="com.example.SessionService">
        <strategy attribute-name="ROLE" attribute-value="USER">
            <filter class="com.example.User">
                <field name="password"/>
            </filter>
        </strategy>

    </controller>
</config>


Description of XML Tags

  • config — main tag
  • controller — in this TAG, you may set the class-name property. Set the Service class name where it is used in this configuration
  • strategy — this TAG is similar to the SessionStrategyannotation
  • filter — this TAG is similar to the FieldFilterSettingannotation

Note: configuration files could be changed after the application starts and the controller will correctly reload all changed files. Don’t worry about it!

Spring Controller Filtration

If you don’t want to add filter annotations to each Service Response, you can add an annotation on the whole Service Controller.

Annotation Example

@FileFilterSetting(fileName = "filter_configuration.xml")
@RestController
public class SessionService {
    @Autowired
    private UserController userController;  

    @RequestMapping(value = "/users/signIn",
            params = {"email", "password"}, method = RequestMethod.POST,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
            produces = {MediaType.APPLICATION_JSON_VALUE})            
    public User signIn(@RequestParam("email") String email, @RequestParam("password") String password) {
        return userController.signInUser(email, password);
    }
}


You can declare all of the required filters.

Dynamic Filter

Using this type of filter, you can create your own filter with custom behavior. All dynamic filters should implement the DynamicFilterEvent.class, and the filter should be annotated by theDynamicFilterComponent annotation.

Dynamic Custom Filter Example

@DynamicFilterComponent
    public class DemoIdFilter implements DynamicFilterEvent {
        @Override
        public FilterFields onGetFilterFields(MethodParameter methodParameter, RequestSession request) {
            if(request.getSession().getAttribute("SOME_VALUE") != null) {
                return new FilterFields(User.class, Arrays.asList("id", "password", "email"));
            } else
                return new FilterFields();
        }
    }


In this example, we created the DemoIdFilter that attempts to find the attribute SOME_VALUE in an Http Session. If the attribute exists, the event onGetFilterFieldsreturns a configured FilterFields. As you can see, FilterFields contains a filter for the User.class. If the Response Body of the Spring Service contains an object instance of the User.class, it will be filtered and the fields id, password, email will be removed from the response.

Annotation Example

@DynamicFilter(DemoIdFilter.class)
    @RequestMapping(value = "/users/signIn",
            params = {"email", "password"}, method = RequestMethod.POST,
            consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
            produces = {MediaType.APPLICATION_JSON_VALUE})            
    public User signIn(@RequestParam("email") String email, @RequestParam("password") String password) {
        return userController.signInUser(email, password);
    }


With this filter, you get huge space for Service Response customization.

Check out these links to learn more:

  • JFilter Main page link
  • JFilter GitHub project page link

Conclusion

In the world of big data and complex systems, sometimes, we need to control and flexibly change data. Maybe this solution is not the best, but I hope it will save you some extra time. You can use it in your projects without the “rain dance” and still achieve your desired result.

Web Service Spring Framework Filter (software) Annotation Object (computer science)

Opinions expressed by DZone contributors are their own.

Related

  • Dependency Injection in Spring
  • Filtering Java Collections via Annotation-Driven Introspection
  • Spring Microservice Application Resilience: The Role of @Transactional in Preventing Connection Leaks
  • Mastering Spring: Synchronizing @Transactional and @Async Annotations With Various Propagation Strategies

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!