Skip to content

Commit 94d7558

Browse files
committed
refactor: update AccessAwareJsonFilter and AccessAwareJsonViewAdvice for Jackson 3.x compatibility
1 parent af9e19b commit 94d7558

2 files changed

Lines changed: 51 additions & 27 deletions

File tree

essencium-backend/src/main/java/de/frachtwerk/essencium/backend/controller/access/AccessAwareJsonFilter.java

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,18 @@
1919

2020
package de.frachtwerk.essencium.backend.controller.access;
2121

22-
import com.fasterxml.jackson.core.JsonGenerator;
23-
import com.fasterxml.jackson.databind.SerializerProvider;
24-
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
25-
import com.fasterxml.jackson.databind.node.ObjectNode;
26-
import com.fasterxml.jackson.databind.ser.PropertyFilter;
27-
import com.fasterxml.jackson.databind.ser.PropertyWriter;
2822
import de.frachtwerk.essencium.backend.model.Ownable;
2923
import de.frachtwerk.essencium.backend.model.dto.EssenciumUserDetails;
3024
import java.io.Serializable;
3125
import java.util.Arrays;
3226
import java.util.stream.Stream;
3327
import lombok.AllArgsConstructor;
3428
import org.springframework.security.core.GrantedAuthority;
29+
import tools.jackson.core.JsonGenerator;
30+
import tools.jackson.databind.SerializationContext;
31+
import tools.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
32+
import tools.jackson.databind.ser.PropertyFilter;
33+
import tools.jackson.databind.ser.PropertyWriter;
3534

3635
@AllArgsConstructor
3736
public class AccessAwareJsonFilter<
@@ -40,9 +39,10 @@ public class AccessAwareJsonFilter<
4039
private AUTHUSER principal;
4140

4241
@Override
43-
public void serializeAsField(
44-
Object pojo, JsonGenerator jsonGenerator, SerializerProvider provider, PropertyWriter writer)
42+
public void serializeAsProperty(
43+
Object pojo, JsonGenerator jsonGenerator, SerializationContext context, PropertyWriter writer)
4544
throws Exception {
45+
4646
JsonAllowFor ann = writer.getMember().getAnnotation(JsonAllowFor.class);
4747
if (ann == null
4848
|| Arrays.stream(ann.roles())
@@ -58,32 +58,26 @@ public void serializeAsField(
5858
.map(GrantedAuthority::getAuthority)
5959
.anyMatch(r::equals))
6060
|| (ann.allowForOwner() && isOwner(pojo))) {
61-
writer.serializeAsField(pojo, jsonGenerator, provider);
62-
} else if (!jsonGenerator.canOmitFields()) {
63-
writer.serializeAsOmittedField(pojo, jsonGenerator, provider);
61+
writer.serializeAsProperty(pojo, jsonGenerator, context);
62+
} else if (!jsonGenerator.canOmitProperties()) {
63+
writer.serializeAsOmittedProperty(pojo, jsonGenerator, context);
6464
}
6565
}
6666

6767
@Override
6868
public void serializeAsElement(
6969
Object elementValue,
7070
JsonGenerator jsonGenerator,
71-
SerializerProvider provider,
71+
SerializationContext context,
7272
PropertyWriter writer)
7373
throws Exception {
7474
// For array/collection elements, just serialize normally
75-
writer.serializeAsField(elementValue, jsonGenerator, provider);
75+
writer.serializeAsProperty(elementValue, jsonGenerator, context);
7676
}
7777

7878
@Override
7979
public void depositSchemaProperty(
80-
PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) {
81-
// Default implementation - include all properties in schema
82-
}
83-
84-
@Override
85-
public void depositSchemaProperty(
86-
PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) {
80+
PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializationContext context) {
8781
// Default implementation - include all properties in schema
8882
}
8983

@@ -95,4 +89,9 @@ private boolean isOwner(Object obj) {
9589
return false;
9690
}
9791
}
92+
93+
@Override
94+
public PropertyFilter snapshot() {
95+
return this;
96+
}
9897
}

essencium-backend/src/main/java/de/frachtwerk/essencium/backend/controller/advice/AccessAwareJsonViewAdvice.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
package de.frachtwerk.essencium.backend.controller.advice;
2121

22+
import de.frachtwerk.essencium.backend.controller.access.AccessAwareJsonFilter;
2223
import de.frachtwerk.essencium.backend.model.dto.EssenciumUserDetails;
2324
import jakarta.annotation.Nonnull;
25+
import org.springframework.beans.factory.annotation.Autowired;
2426
import org.springframework.core.MethodParameter;
2527
import org.springframework.http.MediaType;
2628
import org.springframework.http.converter.HttpMessageConverter;
@@ -29,14 +31,25 @@
2931
import org.springframework.security.core.context.SecurityContextHolder;
3032
import org.springframework.web.bind.annotation.RestControllerAdvice;
3133
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
34+
import tools.jackson.databind.ObjectMapper;
35+
import tools.jackson.databind.ser.FilterProvider;
36+
import tools.jackson.databind.ser.std.SimpleFilterProvider;
3237

3338
@RestControllerAdvice
3439
public class AccessAwareJsonViewAdvice implements ResponseBodyAdvice<Object> {
3540
public static final String FILTER_NAME = "roleBasedFilter";
3641

42+
private final ObjectMapper objectMapper;
43+
44+
@Autowired
45+
public AccessAwareJsonViewAdvice(ObjectMapper objectMapper) {
46+
this.objectMapper = objectMapper;
47+
}
48+
3749
@Override
3850
public boolean supports(
39-
@Nonnull MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
51+
@Nonnull MethodParameter returnType,
52+
@Nonnull Class<? extends HttpMessageConverter<?>> converterType) {
4053
// Support both Jackson2 (deprecated) and Jackson3 converters
4154
String converterName = converterType.getName();
4255
return converterName.contains("Jackson") && converterName.contains("HttpMessageConverter");
@@ -64,11 +77,23 @@ public Object beforeBodyWrite(
6477
return body;
6578
}
6679

67-
/*
68-
TODO: MappingJacksonValue is deprecated in Spring Boot 7.0 and causes wrapped responses
69-
For now, return the body directly without filtering
70-
A proper Jackson 3.x solution needs to be implemented using @JsonFilter on model classes
71-
*/
72-
return body;
80+
// Create FilterProvider with role-based filter (Jackson 3.x API)
81+
FilterProvider filters =
82+
new SimpleFilterProvider()
83+
.addFilter(FILTER_NAME, new AccessAwareJsonFilter<>(principal))
84+
.setFailOnUnknownId(false);
85+
86+
// Configure a temporary ObjectMapper with the filter
87+
// In Jackson 3.x we use rebuild() and filterProvider()
88+
try {
89+
ObjectMapper filteredMapper = objectMapper.rebuild().filterProvider(filters).build();
90+
91+
// Serialize and deserialize to apply the filters
92+
String json = filteredMapper.writeValueAsString(body);
93+
return filteredMapper.readValue(json, Object.class);
94+
} catch (Exception e) {
95+
// On error, return the original body
96+
return body;
97+
}
7398
}
7499
}

0 commit comments

Comments
 (0)