7

Я пытаюсь использовать функцию SpringClassConverter Spring с моим проектом Spring MVC. (У меня есть только базовые знания Spring MVC и Spring, извиняюсь заранее за любой наивный вопрос здесь).Проблемы с использованием SpringClassConverter Spring Spring MVC

От API docs:

The DomainClassConverter allows you to use domain types in your Spring MVC controller 
method signatures directly, so that you don't have to manually lookup the instances via 
the repository: (PS: Example 1.20) 

То, что я понял из сказанного выше, что я не должен написать метод поиска и Spring поставляет User объект. Итак, это шаги, которые я сделал:

Включенная ниже строка XML в applicationcontext.xml.

<bean class="org.springframework.data.web.config.SpringDataWebConfiguration" /> 
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
<property name="converters"> 
    <list> 
     <bean class="com.rl.userservice.controller.UserConverter"/> 
    </list> 
</property> 

Включено эту зависимость в моем pom.xml согласно Spring Data REST документ:

<dependencies> 
    <dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-rest-webmvc</artifactId> 
     <version>2.0.0.BUILD-SNAPSHOT</version> 
    </dependency> 
</dependencies> 

Мой контроллер выглядит как ниже:

@Controller 
@RequestMapping(value = "/api/newuser") 
public class NewUserServiceController { 
     @Autowired 
    NewUserRepository newUserRepository; 

    @RequestMapping("/{id}") 
    public String showUserForm(@PathVariable("id") NewUser newUser, Model model) { 

     model.addAttribute("newUser", newUser); 
     return "userForm"; 
    } 
} 

Repository, как это:

@Repository 
public interface NewUserRepository extends JpaRepository<NewUser, Integer> { 
} 

Это мой конвертер услуг:

final class UserConverter implements Converter<Integer, NewUser> { 
    NewUserRepository newUserRepository; 

    public NewUser convert(Integer username) { 
     return newUserRepository.findOne(username); 
    } 
} 

При запуске программа кот начинает успешно, но при обращении к URL локальный: 8080/UserService/api/newuser/1 Я получаю следующее исключение:

type Exception report 
    message 
    description The server encountered an internal error() that prevented it from fulfilling this request. 
    exception 
    org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 
'com.mpp.userservice.domain.NewUser'; nested exception is 
java.lang.IllegalStateException: Cannot convert value of type 
[java.lang.String] to required type 
[com.mpp.userservice.domain.NewUser]: no matching editors or 
conversion strategy found 
     org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:71) 
     org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) 
     org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) 
     org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:101) 
     org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) 
     org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) 
     org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123) 
     org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) 
     org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
     org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) 
     org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) 
     org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) 
     org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
     org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 

    root cause 
    java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type 
[com.mpp.userservice.domain.NewUser]: no matching editors or 
conversion strategy found 
     org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:264) 
     org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:93) 
     org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:61) 
     org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) 
     org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) 
     org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:101) 
     org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) 
     org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) 
     org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123) 
     org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) 
     org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
     org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) 
     org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) 
     org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) 
     org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
     org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 

    note The full stack trace of the root cause is available in the Apache Tomcat/6.0.29 logs. 
    mpp. 

Хотя не лучший код, вот мой контроллер:

public @ResponseBody ResponseEntity<ModelMap> getUserTypeJSON(@PathVariable("userID" String userID, HttpServletResponse response) { 
    UserType UserType = UserTypeRepository.findOne(id); 
    model.addAttribute("Name",UserType.getName()); 
    ... 
} 

Существует пример here, что я ссылку, но это, используя пользовательский конвертер, но, кажется, не использует службу доменных преобразователя. Пожалуйста, порекомендуйте. Это путь, если я хочу уменьшить шаблонный код написания операций CRUD? Какова реальная польза от этого DomainClassConverter, когда я могу получить данные в другом виде?

Обновлено в Оливер Гирке предложение - по-прежнему не работает, та же ошибка

Документ описывает:

<mvc:annotation-driven conversion-service="conversionService" /> 
<bean class="org.springframework.data.repository.support.DomainClassConverter"> 
    <constructor-arg ref="conversionService" /> 
</bean> 

Так что я обновил свой applicationcontext.xml, как показано ниже, но та же проблема :

<mvc:annotation-driven conversion-service="conversionService"/> 

    <bean class="org.springframework.data.repository.support.DomainClassConverter"> 
    <constructor-arg ref="conversionService" /> 
    </bean> 

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name="converters"> 
     <list> 
      <bean class="com.rl.userservice.controller.UserConverter"/> 
     </list> 
    </property> 
    </bean> 

По-прежнему та же проблема.

Обновление: DomainClassConverter работает с Java Config, но не с XML-способом (по крайней мере, экспериментировал с множеством комбинаций, предложенных здесь, а также где в Интернете). Только для тех, кто может быть заинтересован и получить полезную информацию, здесь используется код.

pom.xml (может потребоваться очистку)

<dependency> 
    <groupId>org.springframework.data</groupId> 
    <artifactId>spring-data-rest-webmvc</artifactId> 
    <version>2.0.0.M1</version> 
</dependency> 

<dependency> 
    <groupId>org.springframework.data</groupId> 
    <artifactId>spring-data-jpa</artifactId> 
    <version>1.4.3.RELEASE</version> 
</dependency> 

Файл контроллера (может потребоваться очистку)

@RequestMapping("/domain/{id}") 
    public @ResponseBody ResponseEntity<ModelMap> showDomainUserForm(@PathVariable("id") User userMatch, HttpServletResponse response) { 

    // some code omitted… 

    ModelMap model = new ModelMap();   
    model.addAttribute("DOMAIN-MAP","Domain Controller Service"); 
    model.addAttribute("Name",userMatch.getName()); 
    model.addAttribute("Phone",userMatch.getPhone());           

    // some code omitted… 


    } 

Файл конфигурации Java, собранные с использованием примеров от и resource2. (Может потребоваться зачистку)

package com.rl.userservice.controller; 

import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.data.repository.support.DomainClassConverter; 
import org.springframework.format.support.FormattingConversionService; 
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; 

@Configuration 
@ComponentScan 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurationSupport{ 
    @Bean 
    public RequestMappingHandlerMapping requestMappingHandlerMapping() { 
     RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping(); 
     handlerMapping.setUseSuffixPatternMatch(false); 
     handlerMapping.setUseTrailingSlashMatch(false); 
     return handlerMapping; 
    } 


    @Bean 
    public DomainClassConverter<?> domainClassConverter() { 
     return new DomainClassConverter<FormattingConversionService>(mvcConversionService()); 
    } 

    @Override 
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
     configurer.enable(); 
    } 

} 

Добавьте ниже определение бина в applicationContext.xml

<bean class="com.rl.userservice.controller.WebConfig"/> 
+0

Что такое 'applicationcontext.xml', это ваш контекст сервлета диспетчера? http://stackoverflow.com/questions/3652090/difference-between-applicationcontext-xml-and-spring-servlet-xml-in-spring Теги и конвертеры MVC, вероятно, будут объявлены в контексте, который используется диспетчерским сервлетом - а не контекст веб-приложения корневого приложения. –

+0

Не указывайте свою собственную услугу конвертации (или пользовательский UserConverter). Удалите определение 'conversionService' bean! –

+0

@Pavel вы можете уточнить? В этом случае я думаю, что служба преобразования находится в неправильном контексте, поэтому она затенена тем, что находится в диспетчерском сервлете, но в целом нет ничего плохого в явном объявлении пользовательских компонентов. –

ответ

0

Пожалуйста, посмотрите на relevant section of the reference documentation, чтобы узнать о правильном пути настройте DomainClassConverter.

+0

Я пробовал в решении, но не работает. Я также пробовал ваши другие решения здесь - https://jira.springsource.org/si/jira.issueviews:issue-html/DATACMNS-133/DATACMNS-133.html Есть ли еще проблемы с DomainClassConverter? Последние документы немного отличаются друг от друга. Http://docs.spring.io/spring-data/data-commons/docs/current/reference/htmlsingle/#core.web – oneworld

+1

Я искал в Интернете и не нашел хорошего рабочего образца код. Каждый сайт имеет свой собственный способ делать, но предоставляет лишь частичную информацию. Есть ли какие-то примеры проектов, которые я мог бы полностью упомянуть? – oneworld

+0

Неужели этот вопрос все еще парит? http://forum.spring.io/forum/spring-projects/data/113584-help-with-domainclassconverter-configuration – oneworld

1

URL-адрес String, поэтому {id} также является String. Поэтому ваш сервис должен иметь возможность конвертировать String в NewUser, а не Integer, как у вас.

+0

Этот комментарий для класса UserConverter? Даже при этом ошибка одинакова: public NewUser convert (String username) { return newUserRepository.findOne (Integer.parseInt (имя пользователя)); }} – oneworld

+0

@oneworld Не уверен, если это необходимо, но я с помощью 'FormattingConversionServiceFactoryBean', а не' ConversionServiceFactoryBean' – zeroflagL

0

ref говорит

В настоящее хранилище должно осуществлять CrudRepository быть право быть обнаруженным для преобразования.

Разве это не причина?

+0

JpaRepository расширяет PagingAndSortingRepository, который в свою очередь расширяет CrudRepository, так что не должно быть проблемой – lilalinux

0

Эта конфигурация устанавливает службу пользовательского преобразования и передает его в аннотаций механизм сканирования, который обнаруживает и настраивает контроллеры:

<bean name="conversionService" class="rest.gateway.services.MyConversionService"/> 

<mvc:annotation-driven conversion-service="conversionService" /> 

И это код пользовательского контроллера, клиент будучи доменным классом как Пользователь:

public class MyConversionService extends DefaultConversionService { 

    public MyConversionService() { 
     super(); 
     addConverter(String.class, Customer.class, new Converter<String, Customer>() { 
      @Override 
      public Customer convert(String source) { 
       return new Customer("123456","Doe","John"); 
      } 
     }); 
    } 
} 

У попробовать с этим, потому что это работает для версии 2.0.0.M1:

<dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-rest-webmvc</artifactId> 
     <version>2.0.0.M1</version> 
    </dependency> 

<repositories> 
    <repository> 
     <id>spring-milestones</id> 
     <name>Spring Milestones</name> 
     <url>http://repo.spring.io/milestone</url> 
     <snapshots> 
      <enabled>false</enabled> 
     </snapshots> 
    </repository> 
</repositories> 
+0

это основано в http://docs.spring.io/spring-data/jpa/docs/1.4.x/reference/html/repositories.html#d0e1111, я использовал его и могу подтвердить, что он работает –

+0

Действительно ли мне нужно написать собственный конвертер для класса конвертера домена? Разве это не дефлирование цели? – oneworld