Issue with JAX-RS JSON unmarshalling in wildfly 26

huangapple go评论76阅读模式
英文:

Issue with JAX-RS JSON unmarshalling in wildfly 26

问题

你在Wildfly 25+版本中遇到了JSON列表反序列化的问题。你是否尝试过在Wildfly 25+中进行特定的配置以正确反序列化JSON列表?

英文:

I am creating a war file to be deployed on wildfly, that serves xml/json api web services;

I am using xjc to generate classes to be used by the webservice as follows

	<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxb2-maven-plugin</artifactId>
				<version>2.5.0</version>
				<executions>
					<execution>
						<id>xjc</id>
						<goals>
							<goal>xjc</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<xjbSources>
						src/main/resources/binding
					</xjbSources>
					<sources>
						<source>src/main/resources/xsd</source>
					</sources>
					<packageName>org.exp.binding</packageName>
					<outputDirectory>target/generated-sources</outputDirectory>
					<clearOutputDir>true</clearOutputDir>
				</configuration>
			</plugin>

I am using a simple global binding:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
	xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema"
	
	xsi:schemaLocation="../xsd/schema.xsd" jaxb:version="1.0">

 <jaxb:globalBindings>
        <xjc:simple/>
    </jaxb:globalBindings>
</jaxb:bindings>

I have a simple schema, which has an object with a property that is derived from a complext type and a property with a list the same type as follows

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">


	<xs:element name="topLevelObject">
	
		<xs:complexType>
			<xs:sequence>
				<xs:element name="singleAttributes" type="attribute" maxOccurs="1"/>
				<xs:element name="multiAttributes" type="attribute" maxOccurs="10"/>
			</xs:sequence>
		</xs:complexType>
	</xs:element>


	<xs:complexType name="attribute">
		<xs:simpleContent>
			<xs:extension base="xs:string">
				<xs:attribute name="id" type="xs:string" />
				<xs:attribute name="name" use="required"
					type="xs:string" />
			</xs:extension>
		</xs:simpleContent>
	</xs:complexType>

<xs:element name="attribute" type="attribute" />

</xs:schema>

This generates an object as follows

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.2 
// See <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2023.06.29 at 08:41:14 AM CEST 
//


package org.wipo.exp.binding;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * <complexType>
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="singleAttributes" type="{}attribute"/>
 *         <element name="multiAttributes" type="{}attribute" maxOccurs="10"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "singleAttributes",
    "multiAttributes"
})
@XmlRootElement(name = "topLevelObject")
public class TopLevelObject {

    @XmlElement(required = true)
    protected Attribute singleAttributes;
    @XmlElement(required = true)
    protected List<Attribute> multiAttributes;

    /**
     * Gets the value of the singleAttributes property.
     * 
     * @return
     *     possible object is
     *     {@link Attribute }
     *     
     */
    public Attribute getSingleAttributes() {
        return singleAttributes;
    }

    /**
     * Sets the value of the singleAttributes property.
     * 
     * @param value
     *     allowed object is
     *     {@link Attribute }
     *     
     */
    public void setSingleAttributes(Attribute value) {
        this.singleAttributes = value;
    }

    /**
     * Gets the value of the multiAttributes property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the multiAttributes property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getMultiAttributes().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link Attribute }
     * 
     * 
     */
    public List<Attribute> getMultiAttributes() {
        if (multiAttributes == null) {
            multiAttributes = new ArrayList<Attribute>();
        }
        return this.multiAttributes;
    }

}

I have a web service that reads the object and then returns it:

package org.exp.rest;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.wipo.exp.binding.TopLevelObject;


@Path("/applications")
@Produces({ "application/xml", "application/json" })
@Consumes({ "application/xml", "application/json" })
public class ApplicationEndpoint {

	@POST
	@Path("/test")
	public TopLevelObject  test(TopLevelObject tlo) {
		return tlo;
	}
	
	
}

Now all this works fine on Wildfly versions from 11 to 23

curl -X POST -d '{"singleAttributes":{"name":"abc","value":"1234"}, "multiAttributes":[{"name":"abc","value":"1234"}]}' -H "Content-Type: application/json" -v localhost:8080/exp-0.0.1-SNAPSHOT/rest/applications/test
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying ::1:8080...
* TCP_NODELAY set
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /exp-0.0.1-SNAPSHOT/rest/applications/test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.65.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 101
>
* upload completely sent off: 101 out of 101 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/xml;charset=UTF-8
< Content-Length: 190
< Date: Thu, 29 Jun 2023 06:21:25 GMT
<
* Connection #0 to host localhost left intact
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><topLevelObject><singleAttributes name="abc">1234</singleAttributes><multiAttributes name="abc">1234</multiAttributes></topLevelObject> 

But from wildfly 25+ the list is not unmarshalled

curl -X POST -d '{"singleAttributes":{"name":"abc","value":"1234"}, "multiAttributes":[{"attribute":{"name":"abc","value":"1234"}}]}' -H "Content-Type: application/json" -v localhost:8080/exp-0.0.1-SNAPSHOT/rest/applications/test
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying ::1:8080...
* TCP_NODELAY set
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /exp-0.0.1-SNAPSHOT/rest/applications/test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.65.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 115
>
* upload completely sent off: 115 out of 115 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/xml;charset=UTF-8
< Content-Length: 140
< Date: Thu, 29 Jun 2023 09:18:44 GMT
<
* Connection #0 to host localhost left intact
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><topLevelObject><singleAttributes name="abc">1234</singleAttributes></topLevelObject>  

Is there some specific config i should add to wildfly versions beyond 25 to unmarshall lists in json correctly?

If I send the message in xml it works correctly, this behavior seems limited to json.

答案1

得分: 0

在WildFly 24中,已经进行了一个切换,从默认使用Jackson进行JSON处理,改为使用Jakarta JSON Binding进行处理。后者不支持JAXB注解。

简单的解决方法是为multiAttributes添加一个setter方法。类似于:

public void setMultiAttributes(final Collection<Attribute> attributes) {
    if (attributes != null) {
        this.multiAttributes = List.copyOf(attributes);
    }
}

如果你愿意的话,也可以启用Jackson。请注意,该文档适用于WildFly 28,但在WildFly 26上应该也能正常工作。

英文:

In WildFly 24 there was a switch made to switch from using Jackson by default for JSON processing to Jakarta JSON Binding processing. The latter does not support the JAXB annotations.

The simple solution is to simply add a setter for the multiAttributes. Something like:

<!-- language: lang-java-->

public void setMultiAttributes(final Collection&lt;Attribute&gt; attributes) {
    if (attributes != null) {
        this.multiAttributes = List.copyOf(attributes);
    }
}

You could also enable Jackson if you'd prefer as well. Note that documentation is for WildFly 28, but it should work the same for WildFly 26.

huangapple
  • 本文由 发表于 2023年6月29日 20:34:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76581118.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定