2

I am using eclipse-link, and I am retrieving data from table and trying to store the retrieved data into XML file using JAXB. While writing into XML file last record only saved in that file.

Here User is My POJO class have Two fields

@XmlRootElement
public class User implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

private  String name;

@XmlAttribute
public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}
@XmlElement
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

 public User()
{

}
}

Below is My code:

public class ObjectToXml {
private static int startingIndex = 0;
private static int maxIndex= 10;

public static void main(String[] args) {

    EntityManager entityManager = EntityManagerUtil.getEmf()
            .createEntityManager();
    Query query = entityManager.createQuery("Select u from User u");

    System.out.println("Total Number of Records"
            + query.getResultList().size());
    try {

        JAXBContext contextObj = JAXBContext.newInstance(User.class);

        Marshaller marshallerObj = contextObj.createMarshaller();
        marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);          

        query.setFirstResult(startingIndex );
        query.setMaxResults(maxIndex);
        List<User> user = query.getResultList();

        Iterator iterator = user.iterator();
        while (iterator.hasNext()) {
            User student = (User) iterator.next();  
        MarshallerObj.marshal(student, new FileOutputStream("User.xml"));

        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    finally {
        entityManager.close();

    }
}
}

Here i am getting 10 records.But while storing last Record only saved in XML

My Result :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<user id="10">
<name>prabha</name> 
</user> 
Prabha
  • 707
  • 2
  • 11
  • 27

4 Answers4

2

Because MarshallerObj.marshal(student, new FileOutputStream("User.xml")); creating new file o/p stream everytime and that clears prev contents. create this instance of o/p stream out of your while loop. that should help.

Sanjeev
  • 9,876
  • 2
  • 22
  • 33
  • Thank you,I put that one in out side of the while loop but the result is same.I created new object for user outside of loop also – Prabha Feb 13 '14 at 10:43
  • Try writing to System.out instead file output stream and see what it prints – Sanjeev Feb 13 '14 at 10:48
  • It's printing 10 objects. – Prabha Feb 13 '14 at 10:51
  • post your code block that has file o/p stream and while loop – Sanjeev Feb 13 '14 at 10:58
  • com.company.User@45389b3f com.company.User@758689a com.company.User@3d3b5a3a com.company.User@3a0b53e com.company.User@2bdafb4e com.company.User@535c97e4 com.company.User@63f8247d com.company.User@3823bdd1 com.company.User@32830122 com.company.User@36bf7916 – Prabha Feb 13 '14 at 11:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/47407/discussion-between-prabha-and-sanjeev) – Prabha Feb 13 '14 at 11:04
1

Perhaps you should keep one single FileOutputStream and marshall continuously into it instead of creating a new one on every iteration.

Smutje
  • 17,733
  • 4
  • 24
  • 41
1

Since you are creating xml file for each User object, the objects will be keep on replacing when the program is taking an new User from DB
So create a POJO class Users with List of User as an attribute,

public class Users 
{
//Users grouping
private List<User> user;

public void setUser(List<ProductInfo> userInfo) 
{
    this.user = userInfo;
}

@XmlElement(name="user")
public List<User> getUser() {
    return user;
}

}

Then in the code section create instance of JAXBContext for the class Users, like mentioned below

 JAXBContext contextObj = JAXBContext.newInstance(Users.class);

Now modify the while loop to set all user's information into Users object, and marshar the Users object than marshaling the User object.

Users users = new Users();
while (iterator.hasNext()) {
      User student = (User) iterator.next();  
      users.setUser(student);
}
MarshallerObj.marshal(users, new FileOutputStream("User.xml"));
Sanoop
  • 1,012
  • 9
  • 6
  • I edited your code now, and I got o/p with help of your code only.Thank you very much @user3156284 – Prabha Feb 13 '14 at 11:41
1

You will need to use @XmlElements annotation.

Marshaller.marshal() simply converts the object into byte stream and writes into output stream. Hence it will override the existing data in ouputstream. In your case, since marshallerObj.marshal(student, new FileOutputStream("User.xml")); is inside a loop, the final file would always contain the last object in the list. I.e in the first iteration it will write first object to the file, in second iteration it will overwrite the file with second object, in third iteration it will overwrite the file with third object and so on.

To marshal a list of objects, one of the solution is to create a container object which will maintain a list of all users/students and then marshal the container object.

Refer to link for similar question.

In your case the container class should look something like:

@XmlRootElement(name = "Users")
public class Users
{
    private List<User> users = new ArrayList<User>();

    @XmlElements(value = {@XmlElement(name = "User", type = User.class)})
    @XmlElementWrapper
    public List<User> getUsers() {
        return users;
    }

    public void addUser(User user) {
        users.add(user);
    }
}

And the code to marshal the Users:

Users users = new Users();

List<User> usersList = query.getResultList();

for(User user : usersList) {
    users.addUser(user);
}

marshallerObj.marshal(users, new FileOutputStream("User.xml"));
Community
  • 1
  • 1
Sanket Meghani
  • 885
  • 2
  • 14
  • 22