我正在尝试将一个大型复杂的项目从Wildfly 23升级到Wildfly 26,但Json响应不再返回我们期望的有效负载。以下是两个例子:
- Package 列表的对象应该返回 Package 列表的Json数组,但它将返回 Package 对象和列表一起,即它应该返回
[ ... ]
,但它正在返回{ "objects": [ ... ] }
。
Package 器类在列表getter方法上使用**@JsonValue**,这应该使其工作,但列表类上的自定义序列化器没有被调用。
1.使用@JsonFormat(pattern = ...some pattern...)
注解的日期字段不会被格式化。
它是一个Java 11项目(11.0.14.1,Eclipse Adoptium),使用Maven 3.6.3创建一个部署到Wildfly 26(构建在Windows 10 Enterprise上并部署到Windows Server 2019 Standard)的WAR文件。我创建了一个非常精简的示例来说明行为(下面显示的类/文件)。
我使用mvn clean verify
构建了这个项目,它创建了target\jsontest.war,然后将其复制到standalone\deployments目录,在那里它可以成功部署。使用了一个自定义登录模块,但我不认为它与问题有关,因为正在到达端点。
server.log中有两个警告,我认为它们不相关:
WARN [org.jboss.as.dependency.deprecated] (MSC service thread 1-5) WFLYSRV0221: Deployment "deployment.jsontest.war" is using a deprecated module ("javax.api") which may be removed in future versions without notice.
WARN [org.jboss.as.dependency.deprecated] (MSC service thread 1-5) WFLYSRV0221: Deployment "deployment.jsontest.war" is using a deprecated module ("org.jboss.resteasy.resteasy-jaxrs") which may be removed in future versions without notice.
任何帮助,使这一工作将不胜感激。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jsontest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.7</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>jsontest</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<webResources>
<resource>
<directory>${project.basedir}/src/main/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
在src/main/java/org/example/jsontest下有以下类:
MainResource.java
package org.example.jsontest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
@Path("/")
public class MainResource {
@GET
@Path("json")
@Produces({ MediaType.APPLICATION_JSON })
public Response getJsonExample() {
// We want to return a Json array containing 2 objects
final SomeObject object1 = new SomeObject().setA("a1").setB("b1");
final SomeObject object2 = new SomeObject().setA("a2").setC("c2");
final ResponseList<SomeObject> objectList = new ResponseList<>();
objectList.addAll(List.of(object1, object2));
final ResponseListWrapper<SomeObject> wrapper = new ResponseListWrapper<>();
wrapper.setObjects(objectList);
return Response.ok(wrapper).build();
}
}
ResponseListWrapper.java
package org.example.jsontest;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonValue;
@JsonInclude(value = Include.NON_NULL)
public class ResponseListWrapper<T> {
private ResponseList<T> objects;
public ResponseListWrapper() {
objects = new ResponseList<>();
}
public ResponseListWrapper(ResponseList<T> objects) {
setObjects(objects);
}
/**
* @JsonValue is supposed to indicate that the value from the method is to be used to produce the Json output.
* We want to return a Json array, not the wrapped object with an array, i.e.
*
* [ { "a": "a1", "b": "b1" }, { "a": "a2", "c": "c2" } ]
*
* But instead we get the wrapped object:
* { "objects": [ { "a": "a1", "b": "b1" }, { "a": "a2", "c": "c2" } ] }
*
* ResponseList is annotated with @JsonSerialize(using = JacksonListSerializer.class)
* but JacksonListSerializer.serialize() is never called.
*
*/
@JsonValue
public ResponseList<T> getObjects() {
return objects;
}
public void setObjects(ResponseList<T> objects) {
this.objects = objects;
}
}
ResponseList.java
package org.example.jsontest;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.ArrayList;
import java.util.Collection;
/**
*
* @JsonSerialize is supposed to tell Jackson to use JacksonListSerializer when generating a Json response but it is not
* being called.
*/
@JsonSerialize(using = JacksonListSerializer.class)
public class ResponseList<T> extends ArrayList<T> {
private static final long serialVersionUID = -6120242076197274777L;
public ResponseList() {
}
public ResponseList(Collection<? extends T> c) {
super(c);
}
public ResponseList(int initialCapacity) {
super(initialCapacity);
}
}
JacksonListSerializer.java
package org.example.jsontest;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class JacksonListSerializer extends JsonSerializer<ResponseList<?>> {
@Override
public void serialize(ResponseList<?> list, JsonGenerator generator, SerializerProvider provider)
throws IOException {
generator.writeStartArray();
if (list != null) {
for (Object item : list) {
generator.writeObject(item);
}
}
generator.writeEndArray();
}
}
SomeObject.java
package org.example.jsontest;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SomeObject implements Serializable {
private static final long serialVersionUID = 6725549179169119963L;
private String a;
private String b;
private String c;
public String getA() {
return a;
}
public SomeObject setA(final String a) {
this.a = a;
return this;
}
public String getB() {
return b;
}
public SomeObject setB(final String b) {
this.b = b;
return this;
}
public String getC() {
return c;
}
public SomeObject setC(final String c) {
this.c = c;
return this;
}
}
在src/main/webapp下有以下文件:
jboss-deployment-structure.xml
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.wildfly.security.elytron"/>
<module name="org.wildfly.extension.elytron"/>
<module name="javax.api"/>
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
<module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
jboss-web.xml
<?xml version="1.0"?>
<jboss-web xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.jboss.com/xml/ns/javaee"
version="6.0"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_6_0.xsd">
<security-domain>...removed...</security-domain>
<context-root>/jsontest</context-root>
</jboss-web>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>jsontest</display-name>
<!-- Security related settings have been removed -->
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<path>/jsontest</path>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
</web-app>
1条答案
按热度按时间w80xi6nr1#
终于找到了原因。我们有一个自定义的身份验证/登录模块,它使用自己的Jackson库副本(jackson-core-2.13.4.jar,jackson-databind-2.13.4.2.jar,jackson-annotations-2.13.4.jar)。我将它们从module.xml中删除,并将以下内容添加到module.xml中的依赖项中:
重启Wildfly后,有效载荷按预期返回。我确实按照James的建议使用了
-D"resteasy.preferJacksonOverJsonB"="true"
设置(谢谢!).