I am trying to create an xml file from my data class using JaxB and download it.
I have created marshaller object from java object. However I am unable to return this object as xml file. When I hit that method I get an empty xml file is downloaded. I am newbie to File IO coding, please help me in this regard.
Following is my Controller method
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController{
@RequestMapping(value = PRODUCT_CODE_PATH_VARIABLE_PATTERN, method = RequestMethod.GET)
public void downloadProduct(@PathVariable("productCode") @NotNull final String productCode, final HttpServletRequest request, final HttpServletResponse response) throws Exception
{
response.setContentType("application/xml");
response.setHeader("Content-Disposition", "attachment; filename=" + productCode + ".xml");
final ProductDataJaxb productDataJaxb = getProductJaxObj(productCode);
final JAXBContext jaxbContext = JAXBContext.newInstance(ProductDataJaxb.class);
final Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
final OutputStream outputStream = new FileOutputStream(productCode + ".xml");
marshaller.marshal(productDataJaxb, outputStream);
}
}
My data class whose xml representation is what I want in downloaded xml file.
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "Product")
@XmlType(propOrder ={ "code", "categories", "description" })
public class ProductDataJaxb
{
private String code;
private String description;
private List<String> categories;
/**
* @return the code
*/
@XmlElement
public String getCode()
{
return code;
}
/**
* @param code
* the code to set
*/
public void setCode(final String code)
{
this.code = code;
}
/**
* @return the description
*/
@XmlElement
public String getDescription()
{
return description;
}
/**
* @param description
* the description to set
*/
public void setDescription(final String description)
{
this.description = description;
}
/**
* @return the categories
*/
@XmlElement
public List<String> getCategories()
{
return categories;
}
/**
* @param categories
* the categories to set
*/
public void setCategories(final List<String> categories)
{
this.categories = categories;
}
}
After some trial and error I got solution to implement my requirement as follows.
@RequestMapping(value = PRODUCT_CODE_PATH_VARIABLE_PATTERN, method = RequestMethod.GET)
public void downloadProduct(@PathVariable("productCode") @NotNull final String productCode, final HttpServletRequest request,
final HttpServletResponse response) throws Exception
{
response.setContentType("application/xml");
response.setHeader("Content-Disposition", "attachment; filename=" + productCode + ".xml");
final ProductDataJaxb productDataJaxb = getProductJaxObj(productCode);
final JAXBContext jaxbContext = JAXBContext.newInstance(ProductDataJaxb.class);
final Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(productDataJaxb, response.getOutputStream());
}
I only had to pass output Stream object of HttpResponse object to marshal method to get this done. Gosh! I seriously need to study IO concepts now.... :)