Как решить «Ошибка при извлечении ответа для типа [class com. *» В Spring Boot? - PullRequest
0 голосов
/ 15 января 2020

Возможно, вы захотите перейти к моему UPDATE 2 ниже

У меня есть RestController, который работает, потому что, когда я обращаюсь к нему напрямую из браузера, он возвращает ответ JSON. Однако, когда я отправляю запрос от Сервиса в другом ограниченном контексте, я получаю ошибку:

{"timestamp":1579095291446,"message":"Error while extracting response for type 
[class com.path.to.contexttwo.client.dto.WorkerDetails] and content type [application/json]; nested exception is 
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: 
Unexpected character ('<' (code 60)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false');
nested exception is com.fasterxml.jackson.core.JsonParseException: 
Unexpected character ('<' (code 60)): 
expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n at [Source: (PushbackInputStream); 
line: 1, column: 2]","details":"uri=/context-two/register-new"}

Вот мой код:

RestController

package com.path.to.contextone.aplication.presentation;

@RestController
@RequestMapping(path = "/iacess", produces = "application/json")
@CrossOrigin(origins = "*")
public class IAccessRestController {

    UserRepository userRepo;
    IAcessService iaccessService;
    EntityLinks entityLinks;

    @Autowired
    public IAccessRestController(
            UserRepository userRepo,
            IAcessService iaccessService,
            EntityLinks entityLinks) {
        this.userRepo = userRepo;
        this.iaccessService= iaccessService;
        this.entityLinks = entityLinks;
    }

    @GetMapping("/get-worker-details/{userName}")
    public WorkerDetails getWorkerDetails(@PathVariable String userName) {

        User user = userRepo.findByUsername(userName);

        WorkerDetails workerDetails = new WorkerDetails();
        workerDetails.setUserId(userId);
        workerDetails.setGender(user.gender());
        workerDetails.setFirstName(user.getFirstName());
        workerDetails.setLastName(user.getLastName());
        workerDetails.setPhoneNumber(user.getPhoneNumber());

        if (workerDetails != null) {
            return workerDetails;
        }
        return null;
    }
}

RestClient

package com.path.to.contexttwo.client;

// imports omitted, as well as other code

@Service
public class IAcessRestClientImpl implements IAcessRestClient {

    private final RestTemplate restTemplate;

    @Autowired
    public IAcessRestClientImpl(
            final RestTemplate restTemplate
    ) {
        this.restTemplate = restTemplate;
    }

    @Override
    public WorkerDetails getWorkerDetailsByName(final String userName) throws URISyntaxException {

        Map<String,String> urlVariables = new HashMap<>();
        urlVariables.put("userName", userName);
        return restTemplate.getForObject(
                "http://localhost:8080/iacess/get-worker-details/{userName}",
                WorkerDetails.class,
                urlVariables
        );
    }
}

Конфиг

package com.path.to.contexttwo.configuration;

@Configuration
@EnableWebMvc
public class RestClientConfig {

    @Bean
    public RestTemplate restTemplate() {
        final RestTemplate restTemplate = new RestTemplate();

        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        List<MediaType> mediaTypes = new ArrayList<MediaType>();
        mediaTypes.add(MediaType.APPLICATION_JSON);
        converter.setSupportedMediaTypes(mediaTypes);
        messageConverters.add(converter);
        restTemplate.setMessageConverters(messageConverters);
        restTemplate.getInterceptors().add(new JsonInterceptor());

        return restTemplate;
    }
}

WorkerDetails

package com.path.to.contexttwo.client.dto;

import java.io.Serializable;
import java.util.Objects;

public class WorkerDetails implements Serializable {

    private long userId;
    private String gender;
    private String firstName;
    private String lastName;
    private String phoneNumber;

    public WorkerDetails() {
        this.userId = -1;
        this.gender = null;
        this.firstName = null;
        this.lastName = null;
        this.phoneNumber = null;
    }

    // omitted all args constructor, getters, setters, equals, hascode, toString for simplicity
}

WorkerDetails также существует в пакете com.path.to.contextone.ohs_pl;

Я пробовал 3 дня, чтение и отладку, но безрезультатно. Похоже, что отладчик показывает, что ошибка возникает, когда RestTemplate анализирует WorkerDetails.class.

Я также пытался использовать ComponentScan во всех классах конфигурации, поскольку файлы находятся в отдельных пакетах (в ограниченном контексте), но безуспешно.

Я мог бы просто использовать UserDetailsRepository из класса, который вызывает IAcessRestClient, чтобы получить WorkerDetails, но это сделало бы два разных ограниченных контекста зависимыми от одной и той же схемы базы данных.

Любая помощь будет очень признательна. Я могу опубликовать дополнительный код для каждого запроса.

Заранее спасибо

ОБНОВЛЕНИЕ @SB запросить входные параметры. вот класс, который отправляет параметры:

CompanyServiceImpl

package com.path.to.contexttwo.domain.services;

// imports

@Service
public class CompanyServiceImpl implements CompanyService {

    private CompanyRepository companyRepository;
    private CompanyWorkerRepositoery companyWorkerRepositoery;
    private WorkerDetailsClient workerDetailsClient;
    private WebApplicationContext applicationContext;

    @Autowired
    CompanyServiceImpl (
            CompanyRepository companyRepository,
            CompanyWorkerRepositoery companyWorkerRepositoery,
            WorkerDetailsClient workerDetailsClient,
            WebApplicationContext applicationContext
    ) {
        this.companyRepository = companyRepository;
        this.companyWorkerRepositoery = companyWorkerRepositoery;
        this.workerDetailsClient = workerDetailsClient;
        this.applicationContext = applicationContext;
    }

    @Transactional
    public Company criateCompany(CompanyDTO dto) throws URISyntaxException { 

        if (dto.getLegalyAuthorized() == true && dto.getTerms() == true) {
            Company company = new Company(
                    dto.getCompanyName(),
                    dto.getStateId()
            );
            company = CompanyRepository.save(company);

            // when saving the company, we also need some details from the current logged in user which can be 
            // retrieved from the idendity and access bounded context. We need those details to be saved in this context            

            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            String name = auth.getName();

            WorkerDetails workerDetails = WorkerDetailsClient.getWorkerDetailsByName(
                    name
            );

            // ... we can't reach the rest of the code anyway, so we omitted            
    }
}

А вот ответ, который я получаю, когда обращаюсь к RestController напрямую:

{"userId":127,"gender":"M","firstName":"Primeiro","lastName":"Último","phoneNumber":"922222222"}

ОБНОВЛЕНИЕ 2

Закомментировано .anyRequest (). Authenticated () и все выполнено ОК! Таким образом, все это время связано с Spring Security. Какой позор. Теперь попробую заставить все работать с включенной безопасностью. Я получил HTML в качестве ответа из-за перенаправления на страницу входа. Правильно реализована аутентификация (запрос токена с basi c auth) и все работает хорошо.

Спасибо всем!

1 Ответ

0 голосов
/ 15 января 2020

Попробуйте:

return restTemplate.getForObject(
   "http://localhost:8080/iacess/get-worker-details/" + userName,
   WorkerDetails.class);
...