eclipse-ee4j / jaxb-ri

Jaxb RI
https://eclipse-ee4j.github.io/jaxb-ri/
BSD 3-Clause "New" or "Revised" License
205 stars 111 forks source link

Content of collection properties lost during Unmarshalling #1043

Open Tomas-Kraus opened 10 years ago

Tomas-Kraus commented 10 years ago

Recent versions of JAXB handle collection properties differently than before. An empty collection is created at the beginning, and set into the target bean, and then elements are added to the collection, without any interaction with the bean.

So if the bean for instance makes a private copy of the collection when the setter is called, the content of the collection is lost. See the unit test below.

Issue occurs with version 2.2.10-b140310.1920

package test.serialization.jaxb;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlRootElement;

import org.junit.Test;

@XmlRootElement
public class A {

    protected List<String> list;

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        // Store the list content in a private copy         this.list = new ArrayList<>(list);
    }

    @Test
    public void test() throws Exception {
        A a = new A();
        a.setList(Arrays.asList("something"));

        JAXBContext ctx = JAXBContext.newInstance(A.class);

        StringWriter writer = new StringWriter();

        ctx.createMarshaller().marshal(a, writer);

        String text = writer.toString();
        System.out.println(text);

        A a2 = (A) ctx.createUnmarshaller().unmarshal(new StringReader(text));
        assertNotNull(a2.getList());
        assertEquals(1, a2.getList().size());
        assertEquals("something", a2.getList().get(0));
    }

}

Environment

Bug occurs on version 2.2.10-b140310.1920

Affected Versions

[2.2.10]

Tomas-Kraus commented 6 years ago
Tomas-Kraus commented 10 years ago

@glassfishrobot Commented Reported by killerchamb

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented laune said: Consider; class A1

{ protected List list = new ArrayList<>(); //... }

works, as does class A2 { //... public void setList(List list)

{ this.list = list; }

//... } With class A as shown, the client must provide the implementation for List, apparently leaving it up to him whether it's going to be a LinkedList, an ArrayList or whaterver. But that object isn't returned!

Which, after all, would make a client write code like a.setList( new ArrayList() ); for(String s: ..)

{ ;a.setList( a.getList().add() ); }

because it isn't guaranteed that what you set is what you get; resulting in a markedly inefficient code.

It may be regrettable that JAXB'S behaviour has changed, but I wouldn't expect it to work with a class according to the pattern of class A.

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented yaroska said: Hi @killerchamb,

Why do you think this is a bug?

In any case you can clone the collection after unmarshalling, right?

I'm going to close this as 'Not a bug'

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented killerchamb said: Hi, and thank you for looking at this.

I agree that the new behaviour is not a bug, not more than the previous behaviour at least. It's just that it does not work in a few more cases than before, when the getter/setter methods of a class modify the data. When you can alter the source code of the serialized classes it is very easy to fix, when you cannot it blocks you.

I let you close the ticket, at least there will be a trace of the discussion.

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented yaroska said: The only thing I can imagine is, that we can set already populated collection. I'll give a try.

Thanks for reporting.

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented yaroska said: @me -> https://java.net/jira/browse/JAXB-948

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented Was assigned to yaroska

Tomas-Kraus commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JAXB-1043