How To Represent a class as Spring XML - java

I have a sample class Person and the setter methods need to manipulate the string passed as its argument before setting it to the object. How do we represent this same class as XML in Spring?
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name.substring(0, name.length()-1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
}

You can add below line with relative changes and add it in the spring bean config file.<bean id="referenceName" class="com.stack.overflow.Person"> Read this for more information.

Using XML :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="person" class="com.example.bean.Person">
</bean>
</beans>
Using Bean config class with annotations:
import org.springframework.context.annotation.*;
#Configuration
public class BeanWireConfig {
#Bean
public Person person(){
return new Person();
}
}
Hope this helps..!

Related

Getting NoSuchBeanDefinitionException while Referencing JavaConfig in XML configuration

I am beginner in Spring and trying to learn different ways of configuring Spring beans using XML and Java Config classses. In below demo program, i have configured EmployeeService and EmployeeDAO beans in Java Config classes and Employee bean in XML file. And then i am trying to Reference JavaConfig in XML configuration and use this XML configuration file in Main Class to get the Employee Service bean. I am getting NoSuchBeanDefinitionException while executing the below program. Can someone please help me to understand what is wrong here.
DAOConfig.java
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.demo.dao.EmployeeDAO;
#Configuration
public class DAOConfig {
#Bean
public EmployeeDAO getEmployeeDAO(){
return new EmployeeDAO();
}
}
ServiceConfig.java
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.demo.dao.EmployeeDAO;
import com.demo.service.EmployeeService;
#Configuration
public class ServiceConfig {
#Bean(name="myEmployeeService")
public EmployeeService getEmployeeService(EmployeeDAO empDAO){
EmployeeService empService = new EmployeeService();
empService.setEmpDAO(empDAO);
return empService;
}
}
MainConfig.java
package com.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration
#Import({ DAOConfig.class, ServiceConfig.class })
public class MainConfig {
}
EmployeeService.java:
package com.demo.service;
import com.demo.dao.EmployeeDAO;
public class EmployeeService {
private EmployeeDAO empDAO;
public void setEmpDAO(EmployeeDAO empDAO) {
this.empDAO = empDAO;
}
public void insertEmployee() {
System.out.println("insertEmployee called..");
empDAO.insertEmployeeDetails();
}
public void updateEmployee() {
System.out.println("updateEmployee called..");
empDAO.updateEmployeeDetails();
}
public void deleteEmployee() {
System.out.println("deleteEmployee called..");
empDAO.deleteEmployeeDetails();
}
}
EmployeeDAO.java
package com.demo.dao;
public class EmployeeDAO {
public void insertEmployeeDetails(){
System.out.println("insertEmployeeDetails called..");
}
public void updateEmployeeDetails(){
System.out.println("updateEmployeeDetails called..");
}
public void deleteEmployeeDetails(){
System.out.println("deleteEmployeeDetails called..");
}
}
Employee.java:
package com.demo.dto;
public class Employee {
private String name;
private String id;
private String salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
#Override
public String toString() {
return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]";
}
}
mixAppContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="com.demo.config.MainConfig" />
<bean id="employeeObj" class="com.demo.dto.Employee">
<property name="name" value="ABC"></property>
<property name="id" value="123"></property>
<property name="salary" value="10000"></property>
</bean>
</beans>
JavaConfigInXmlMixDemo.java:
package com.demo.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.demo.dto.Employee;
import com.demo.service.EmployeeService;
public class JavaConfigInXmlMixDemo {
public static void main(String args[]){
//ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
ApplicationContext context = new ClassPathXmlApplicationContext("mixAppContext.xml");
EmployeeService service = (EmployeeService) context.getBean("myEmployeeService");
Employee employee = (Employee) context.getBean("employeeObj");
service.insertEmployee();
service.updateEmployee();
service.deleteEmployee();
System.out.println(employee);
}
}
I am getting below exception:
Exception:
INFO: Loading XML bean definitions from class path resource [mixAppContext.xml]
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myEmployeeService' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:701)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1180)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076)
at com.demo.main.JavaConfigInXmlMixDemo.main(JavaConfigInXmlMixDemo.java:15)
Like described here you need include <context:annotation-config /> in your xml. Without this tag spring will ignore all annotation and create instance of your configuration bean as it's a simple bean.

What is the advantage of #Autowired annotaion?

In my spring example ,I declared two beans with following XML configuration file.
EmployeeBean.java
package autowire;
import org.springframework.beans.factory.annotation.Autowired;
public class EmployeeBean {
private String fullName;
#Autowired
private DepartmentBean departmentBean;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
}
DepartmentBean.java
package autowire;
public class DepartmentBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
spring-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:annotation-config />
<bean id="employee" class="autowire.EmployeeBean" autowire="byType">
<property name="fullName" value="Charith"></property>
</bean>
<bean id="deptment" class="autowire.DepartmentBean">
<property name="name" value="IT Department"></property>
</bean>
</beans>
TestAutowire .java
package autowire;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAutowire {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"spring-servlet.xml"});
EmployeeBean employee = (EmployeeBean)context.getBean("employee");
System.out.println(employee.getFullName());
System.out.println(employee.getDepartmentBean().getName());
}
}
Above example is woking fine.After that I removed '#Autowired' annotation and add following lines to EmployeeBean.java
public void setDepartmentBean(DepartmentBean departmentBean) {
this.departmentBean = departmentBean;
}
Now the example working fine with same output.My question is , What is the actual benefit when used '#Autowired' annotation?Because the code working fine without annotation but with setter method also.Pls help me.
#AutoWired can be useful as it saves you time writing "wiring" code. You don't have to call somewhere in your code the setDepartment method to init your object. Spring will do it for you.
In your case, see below how to accomplish this using annotations only. Note the use of #Component annotation for indicating auto scan components to Spring. Also note that no XML file is now needed.
EmployeeBean.java
package autowire;
/* Imports go here ... */
#Component
public class EmployeeBean {
private String fullName;
#Autowired
private DepartmentBean departmentBean;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public DepartmentBean getDepartmentBean() {
return departmentBean;
}
}
DepartmentBean.java
package autowire;
/* Imports go here ... */
#Component
public class DepartmentBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
TestAutowire .java
package autowire;
/* Imports go here ... */
public class TestAutowire {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("autowire");
context.refresh();
EmployeeBean employee = (EmployeeBean)context.getBean("employee");
System.out.println(employee.getFullName());
System.out.println(employee.getDepartmentBean().getName());
}
}
References:
Spring 3.2.x: Java Based container configuration

Accepting / returning XML/JSON request and response - Spring MVC

I need to write a rest service which accepts XML/JSON as a input (POST method) and XML/JSON as a output (based on the input format). I have tried a below approach to achieve this but doesn't helped out.Endpoint method accepts both XML/JSON but while responding it always gives either JSON or XML based on the order specified in #RequestMapping -produces.Any help will be really appreciated.
My endpoint method:
#RequestMapping(value = "/getxmljson", method = RequestMethod.POST,produces={"application/json","application/xml"},
consumes={"application/json", "application/xml"})
public #ResponseBody Student processXMLJsonRequest(#RequestBody Student student)
throws Exception {
System.out.println("*************Inside Controller");
return student;
}
POJO Class: Student.java
import java.io.Serializable;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#XmlRootElement(name = "student")
#XmlType(propOrder = {"id", "name", "graduationTime", "courses"})
#JsonPropertyOrder({"id", "name", "graduationTime", "courses"})
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private String graduationTime;
private ArrayList<Course> courses = new ArrayList<Course>();
#XmlElement
public int getId() { return id; }
#XmlElement
public String getName() { return name; }
#XmlElement
public String getGraduationTime() { return graduationTime; }
#XmlElement
public ArrayList<Course> getCourses() { return courses; }
public void setId(int value) { this.id = value; }
public void setName(String value) { this.name = value; }
public void setGraduationTime(String value) { this.graduationTime = value; }
public void setCourses(ArrayList<Course> value) { this.courses = value; }
#JsonIgnore
public String toString() {
return this.name + " - "
+ graduationTime == null? "Unknown" : graduationTime.toString();
}
public Student() {}
public Student(int id, String name, String graduationTime) {
this.id = id;
this.name = name;
this.graduationTime = graduationTime;
}
}
POJO Class: Course.java
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#XmlRootElement(name = "course")
#XmlType(propOrder = {"courseName", "score"})
#JsonPropertyOrder({"courseName", "score"})
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
private String courseName;
private Integer score;
public #XmlElement String getCourseName() { return courseName; }
public #XmlElement Integer getScore() { return score; }
public void setCourseName(String value) { courseName = value; }
public void setScore(Integer value) { score = value; }
public Course() {}
public Course(String courseName, Integer score) {
this.courseName = courseName;
this.score = score;
}
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
<beans:ref bean="xmlMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</beans:bean>
<beans:bean id="xmlMessageConverter"
class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter">
</beans:bean>
<beans:bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
</beans:bean>
<beans:bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
<context:component-scan base-package="com.test" />
</beans:beans>
Json Input:
{
"id":2014,
"name":"test",
"graduationtime":"09/05/2014",
"courses":[
{
"courseName":"Math",
"score":150
},
{
"courseName":"Che",
"score":150
}
]
}
XML Input:
<?xml version="1.0" encoding="UTF-8" ?>
<student>
<id>2014</id>
<name>test</name>
<graduationTime>09/05/2014</graduationTime>
<courses>
<courseName>Math</courseName>
<score>150</score>
</courses>
<courses>
<courseName>Che</courseName>
<score>150</score>
</courses>
</student>
The best practice for handling different data formats with the same controller is to let the framework do all the work of figuring out the marshalling and unmarshalling mechanisms.
Step 1: Use minimal controller configuration
#RequestMapping(value = "/getxmljson", method = RequestMethod.POST)
#ResponseBody
public Student processXMLJsonRequest(#RequestBody Student student) {
return student;
}
There is no need to specify consumes and produces here. As an example, consider that you may want this same method to handle other formats in the future such as Google Protocol Buffers, EDI, etc. Keeping the controllers free of consumes and produces will let you add data formats through global configuration instead of having to modify the controller code.
Step 2: Use ContentNegotiatingViewResolver instead of RequestMappingHandlerAdapter
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</list>
</property>
</bean>
Let the view resolver decide how to read incoming data and how to write it back.
Step 3: Use Accepts and Content-Type HTTP headers
Hitting your controller with the correct HTTP header values will force ContentNegotiatingViewResolver to marshal and unmarshal data automatically using the appropriate data representations.
If you want to exchange data in JSON format, set both headers to application/json. If you want XML instead, set both to application/xml.
If you do not want to use HTTP headers (which ideally you should), you can simply add .json or .xml to the URL and ContentNegotiatingViewResolver will do the rest.
You can check out my sample app that I created using your code snippets that works fine for JSON and XML.
Adding to Manish's answer above, if you don't wanna use xml based configuration use this java based configuration instead-
#Bean
public ViewResolver contentNegotiatingViewResolver() {
ContentNegotiatingViewResolver resolver =
new ContentNegotiatingViewResolver();
List<View> views = new ArrayList<>();
views.add(new MappingJackson2XmlView());
views.add(new MappingJackson2JsonView());
resolver.setDefaultViews(views);
return resolver;
}
Register a filter that intercepts each request, warp the HttpServletRequest into an implementation of HttpServletRequestWrapper and returns the Content-Type value for Accept header. For example, you can register a filter named SameInSameOutFilter like following:
#Component
public class SameInSameOutFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
SameInSameOutRequest wrappedRequest = new SameInSameOutRequest((HttpServletRequest) request);
chain.doFilter(wrappedRequest, response);
}
}
It wraps current request in a SameInSameOutRequest:
public class SameInSameOutRequest extends HttpServletRequestWrapper {
public SameInSameOutRequest(HttpServletRequest request) {
super(request);
}
#Override
public String getHeader(String name) {
if (name.equalsIgnoreCase("accept")) {
return getContentType();
}
return super.getHeader(name);
}
}
This wrapper tells spring mvc to select a HttpMessageConverter based on request's Content-Type value. If request body's Content-Type is application/xml, then the response would be an XML. Otherwise, the response would be JSON.
The other solution is to manually set the Accept header along with Content-Type in each request and avoid all these hacks.
i was facing the same problem like yours. Below is my solution and sample.
Below is maven dependency that you need to include:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.4.3</version>
</dependency>
dispatcher-servlet.xml
<mvc:annotation-driven
content-negotiation-manager="contentManager" />
<bean id="contentManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="defaultContentType" value="application/json" />
<property name="useJaf" value="false" />
</bean>
and my #RequestMapping ( you can use your own request mapping )
#RequestMapping(value = "/testXMLJSON",
method = RequestMethod.GET, produces = {
MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE })
#ResponseBody
public ArtworkContentMessageType testXMLJSON()
{
//this is GS1 xml standard mapping.
ArtworkContentMessageType resp = new ArtworkContentMessageType();
StandardBusinessDocumentHeader standarBusinessDocumentHeader = new StandardBusinessDocumentHeader();
resp.setStandardBusinessDocumentHeader(standarBusinessDocumentHeader );
ArtworkContentType artWorkContent = new ArtworkContentType();
resp.getArtworkContent().add(artWorkContent);
return resp ;
}
If application/xml is required then, below headers must be present
Content-Type:application/xml
Accept:application/xml
If the resource define as below
#GET
#Path("/{id}")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Student getStudent(#PathParam("id") String id) {
return student(); // logic to retunrs student object
}
Then the request should contains 'accept' header ('application/json' or application/xml'),
then it returns response in json or xml format.
Sample request :
curl -k -X GET -H "accept: application/json" "https://172.17.0.5:8243/service/1.0/222"
Sample Student class
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "student")
public class Student {
private int id;
private String name;
private String collegeName;
private int age;
#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;
}
#XmlElement
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
public int getAge() {
return age;
}
#XmlElement
public void setAge(int age) {
this.age = age;
}
}

Spring #Qualifier value at runtime

Is it possible to assign #Qualifier value at runtime. Let's say I have two beans of same type and a class with dependency injection
<bean id="typeA" class="com.debopam.test.Type">
<property name="typevalue" value="Export" />
</bean>
<bean id="typeB" class="com.debopam.test.Type">
<property name="typevalue" value="Import" />
</bean>
public class Product {
private Integer price;
private String name;
#Autowired
#Qualifier("typeB")
private Type type;
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public Type getType() {
return type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Is there any way to define type in Product class in runtime instead of hard coding/specifying the value? If yes could you please post some code, otherwise is it advisable to use ApplicationContext.getBean("bean name") to load the bean at runtime?
Yes, I see that you defined two beans for a class. The #Qualifier annotation will tell the class which bean has to be used from the spring configuration file

XML binding with the use of JAXB and Spring-MVC

the following xml is in a repository on a server:
<author xmlns="http://www..." xmlns:atom="http://www.w3.org/2005/atom">
<name>S. Crocker</name>
<address>None</address>
<affiliation></affiliation>
<email>None</email>
</author>
My model class:
#XmlRootElement(name = "author", namespace="http://www...")
#XmlAccessorType(XmlAccessType.FIELD)
public class Author {
#XmlAttribute(name="author")
private String author;
#XmlElement(name="name")
private String name;
#XmlElement(name="address")
private String address;
#XmlElement(name="affiliation")
private String affiliation;
#XmlElement(name="email")
private String email;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAffiliation() {
return affiliation;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
According to a tutorial i saw i should use the #XmlSchema to a package-info.java
I create a class package-info.java but i don't know how to treat this.
Actually my problem is that i don't know how to use the corect annotations to bind the xml with the model class. The whole story is that i'm trying to retrieve an XML document from a repository, but i take null values. The problem as i saw here: JAXB: How to bind element with namespace
is that i don't use the correct annotations. Does anyone knows which are the correct annotations and how should i use them?
Below is an example of how you could map this use case:
package-info
I would use the package level #XmlSchema annotation to specify the namespace qualification. Specify the namespace to be your target namespace ("http://www.../ckp"). You want this namespace applied to all XML elements so specify elementFormDefault=XmlNsForm.QUALIFIED. The use xmlns to asssociate prefixes with your namespace URIs.
#XmlSchema(
namespace="http://www.../ckp",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(prefix="", namespaceURI="http://www.../ckp"),
#XmlNs(prefix="atom", namespaceURI="http://www.w3.org/2005/atom"),
}
)
package forum10388261;
import javax.xml.bind.annotation.*;
Author
Below is what your Author class would look like. I have removed the unnecessary annotations (annotations that were equivalent to the default mapping).
package forum10388261;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Author {
#XmlAttribute
private String author;
private String name;
private String address;
private String affiliation;
private String email;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAffiliation() {
return affiliation;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Demo
package forum10388261;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Author.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum10388261/input.xml");
Author author = (Author) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(author, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<author xmlns:atom="http://www.w3.org/2005/atom" xmlns="http://www.../ckp">
<name>S. Crocker</name>
<address>None</address>
<affiliation></affiliation>
<email>None</email>
</author>
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html
I've never needed to use the namespace parameter on #XmlRootElement, try leaving that off; also, you have #XmlAttribute specified for author, but there's no author in your example besides the tag name.
As for:
Actually my problem is that i don't know how to use the corect
annotations to bind the xml with the model class.
In your spring config you can do:
<oxm:jaxb2-marshaller id="jaxb2Marshaller">
<oxm:class-to-be-bound name="com.mycompany.Author"/>
<!-- ... -->
</oxm:jaxb2-marshaller>
Then inject the jaxb2Marshaller directly or use a MessageConverter like so:
<bean id="xmlConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg>
<ref bean="jaxb2Marshaller"/>
</constructor-arg>
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="xml"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
If you want to use spring's content negotiation, you could then use AnnotationMethodHandlerAdapter with the message converter:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="xmlConverter"/>
<!-- other converters if you have them, e.g. for JSON -->
</list>
</property>
</bean>

Categories

Resources