使用JAXB的基于Java的Spring Restful Web服务配置

时间:2014-02-04 20:31:34

标签: java spring rest spring-mvc jaxb

我在Spring MVC中创建Restful Web Services时遇到了一个问题。我使用的是基于Java的配置而不是基于XML的配置。当我尝试访问服务时,我得到了

Error 500--Internal Server Error
java.lang.NoSuchMethodError: supports
at org.springframework.http.converter.xml.MarshallingHttpMessageConverter.supports(MarshallingHttpMessageConverter.java:109)
at org.springframework.http.converter.AbstractHttpMessageConverter.canWrite(AbstractHttpMessageConverter.java:125)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:136)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:80)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:94)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:69)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:604)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:565)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:779)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:821)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:176)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3498)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)

以下是我的用户域类:

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "userType")
@XmlRootElement(name = "user")
public class User {
private long id;
private String name;
private Date registrationDate;

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getName() {
    return name;
}

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

public Date getRegistrationDate() {
    return registrationDate;
}

public void setRegistrationDate(Date registrationDate) {
    this.registrationDate = registrationDate;
}

@Override
public String toString() {
    return "The Id is"+getId()+"The name is"+getName()+"The registration date"+getRegistrationDate();
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (!(obj instanceof User)) {
        return false;
    }
    User other = (User) obj;
    //EqualsBuilder equalsBuilder = new EqualsBuilder();
    //equalsBuilder.append(getId(), other.getId());
    //return equalsBuilder.isEquals();
    return true;
}

我的用户列表类如下:

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "userListType")
@XmlRootElement(name = "userList",namespace = "com.commercial.mpmapprovals.domain")

public class UserList {
private List<User> users = new ArrayList<User>();

public UserList() {}

public UserList(List<User> users) {
    this.users = users;
}

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

public void setUsers(List<User> users) {
    this.users = users;
   }
}

我的CRUD用户服务实现类如下:

@Service
public class UserServiceImpl implements UserService{
private final AtomicLong USER_ID_SEQ = new AtomicLong();
private final ConcurrentMap<Long, User> usersMap = new ConcurrentHashMap<Long, User>();

@Override
public User create(User user) {
    user.setId(USER_ID_SEQ.incrementAndGet());
    usersMap.put(user.getId(), user);
    return user;
}

@Override
public User read(long userId) {
    return usersMap.get(userId);
}

@Override
public User update(User user) {
    User updatedUser = usersMap.replace(user.getId(), user);
   // Validate.isTrue(updatedUser != null, "Unable to find user with id: " + user.getId());
    return updatedUser;
}


@Override
public User delete(long userId) {
    User removedUser = usersMap.remove(userId);
   // Validate.isTrue(removedUser != null, "Unable to find user with id: " + userId);
    return removedUser;
}

@Override
public Collection<User> list() {
    User user1=new User();
    user1.setId(1L);
    user1.setName("User1");
    user1.setRegistrationDate(new Date());
    usersMap.put(user1.getId(), user1);
    User user2=new User();
    user2.setId(2L);
    user2.setName("User2");
    user2.setRegistrationDate(new Date());
    usersMap.put(user2.getId(), user2);
    return usersMap.values();
    }
}

我的用户控制器如下所示:

@Controller
@RequestMapping(value = "/users")
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);

@Autowired
private UserService userService;

@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public User create(@RequestBody User user) {
    LOGGER.info("Creating new user {}", user);
    return userService.create(user);
}

@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
@ResponseBody
public User read(@PathVariable(value = "userId") long userId) {
    LOGGER.info("Reading user with id {}", userId);
    User user = userService.read(userId);
   // Validate.isTrue(user != null, "Unable to find user with id: " + userId);
    return user;
}

@RequestMapping(value = "/{userId}", method = RequestMethod.PUT)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void update(@PathVariable(value = "userId") long userId, @RequestBody User user) {
    LOGGER.info("Updating user with id {} with {}", userId, user);
   // Validate.isTrue(userId == user.getId(), "userId doesn't match URL userId: " + user.getId());
    userService.update(user);
}

@RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.NO_CONTENT)
public void delete(@PathVariable(value = "userId") long userId) {
    LOGGER.info("Deleting user with id {}", userId);
    userService.delete(userId);
}

@RequestMapping(value = "/users", method = RequestMethod.GET,produces = "application/xml")
@ResponseBody
public UserList list() {
    System.out.println("Inside the List function");
    LOGGER.info("Listing users");
    return new UserList(new ArrayList<User>(userService.list()));
}

@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleClientErrors(Exception ex) {
    LOGGER.error(ex.getMessage(), ex);
    return ex.getMessage();
}

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public String handleServerErrors(Exception ex) {
    LOGGER.error(ex.getMessage(), ex);
    return ex.getMessage();
    }
}

我的POM文件具有以下依赖项

 <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-oxm-tiger</artifactId>
        <version>1.0-m2</version>
 </dependency>
 <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws</artifactId>
            <version>1.5.0</version>
 </dependency>
             <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
  </dependency>

所有其他依赖项也会添加到POM文件

我的基于Java的配置类如下所示:

public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setClassesToBeBound(User.class);
    return marshaller;
}  

@Bean
public Marshaller marshaller() {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setClassesToBeBound(User.class);
    return marshaller;
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    super.configureMessageConverters(converters);

    HibernateModule hibernateModule = new HibernateModule();
    hibernateModule.configure(HibernateModule.Feature.FORCE_LAZY_LOADING, false);

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.registerModule(hibernateModule);

    MappingJacksonHttpMessageConverter jacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
    jacksonHttpMessageConverter.setObjectMapper(objectMapper);

    converters.add(jacksonHttpMessageConverter);

   MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(this.marshaller());
    converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_XML));
    converters.add(converter);
}

我花了很多时间在这上面。对很长的问题我很抱歉。 :-)有些人可以帮帮我吗?非常感谢你。

1 个答案:

答案 0 :(得分:1)

所有已定义的依赖项都包含导致此异常的Unmarshaller接口。你的问题是,其中一些库将supports方法定义为单个参数,有些使用var args。

您可能会发现,如果您使用的是Spring 3.x.x,那么您就不需要旧的老虎罐了。删除它们可能会解决您的问题。