Приложение Spring Boot завершается с ошибкой из-за «отсутствует предыдущий символ открытого захвата» в шаблоне пути, несJAVA

Программисты JAVA общаются здесь
Anonymous
Приложение Spring Boot завершается с ошибкой из-за «отсутствует предыдущий символ открытого захвата» в шаблоне пути, нес

Сообщение Anonymous »

Я столкнулся с ошибкой запуска Spring Boot во время тестов сборки Maven в моем микросервисе рекомендаций. Ошибка указывает на недопустимый шаблон сопоставления/рекомендацию}, но я проверил все сопоставления конечных точек и не обнаружил опечаток с дополнительными фигурными скобками.
Сообщение об ошибке:

Код: Выделить всё

org.springframework.web.util.pattern.PatternParseException:
Missing preceding open capture character before variable name{
...
Invalid mapping pattern detected: /recommendation}
^
Интерфейс службы рекомендаций:

Код: Выделить всё

public interface RecommendationService {
@PostMapping(
value = "/recommendation",
consumes = "application/json",
produces = "application/json")
Recommendation createRecommendation(@RequestBody Recommendation body);

@GetMapping(
value = "/recommendation",
produces = "application/json")
List getRecommendations(@RequestParam(value = "productId") int productId);

@DeleteMapping(value = "/recommendation")
void deleteRecommendation(@RequestParam(value = "productId")  int productId);
}
Класс RecommendationServiceImpl:

Код: Выделить всё

@RestController
public class RecommendationServiceImpl implements RecommendationService {
private final ServiceUtil serviceUtil;
private final RecommendationRepository repository;
private final RecommendationMapper mapper;

public RecommendationServiceImpl(ServiceUtil serviceUtil, RecommendationRepository repository, @Qualifier("recommendationMapperImpl") RecommendationMapper mapper) {
this.serviceUtil = serviceUtil;
this.repository = repository;
this.mapper = mapper;
}

@Override
public Recommendation createRecommendation(Recommendation body) {
try {
RecommendationEntity entity = mapper.apiToEntity(body);
RecommendationEntity newEntity = repository.save(entity);

return mapper.entityToApi(newEntity);
} catch (DuplicateKeyException e) {
throw new InvalidInputException("Duplicate key, Product Id: " + body.getProductId() + ", Recommendation Id:" + body.getRecommendationId());
}
}

@Override
public List getRecommendations(int productId) {
if (productId < 1) {
throw new InvalidInputException("Invalid productId: " + productId);
}

List entityList = repository.findByProductId(productId);
List list = mapper.entityListToApiList(entityList);
list.forEach(e -> e.setServiceAddress(serviceUtil.getServiceAddress()));

return list;
}

@Override
public void deleteRecommendation(int productId) {
repository.deleteAll(repository.findByProductId(productId));
}
}
Реализация RecommendationServiceImpl:

Код: Выделить всё

@RestController
public interface RecommendationRepository extends CrudRepository {
List findByProductId(int productId);
}
Что я пробовал:
  • Искал во всех файлах /recommendation}, используя как IDE, так и grep -ri "/recommendation}" .
    Найдено только одно совпадение:
    ./target/surefire-reports/TEST-com.example.recommendation_service.RecommendationServiceApplicationTests.xml:/recommendation
  • Очистил и пересобрал проект (./mvnw clean install)
  • Проверил точное совпадение всех сопоставлений конечных точек /recommendation (без опечаток)
  • Подтверждено, что приложение работает успешно при прямом запуске (сбой только во время тестов)
  • Экспериментально изменены пути конечных точек к /recommendation1, /recommendation2 и т. д. как в контроллере, так и в тестах.
  • Сообщение об ошибке по-прежнему отображается /recommendation} (без цифр)
Основные наблюдения
  • Ошибка появляется только при запуске тестов
  • При удалении тестового файла ошибка исчезает
  • Ошибка появляется в XML-отчете о тестировании, а не в исходный код
Тестовый файл:

Код: Выделить всё

@SpringBootTest(webEnvironment = RANDOM_PORT)
class RecommendationServiceApplicationTests extends MongoDbTestBase {

@Autowired
private WebTestClient client;

@Autowired
private RecommendationRepository repository;

@BeforeEach
void setupDb() {
repository.deleteAll();
}

@Test
void getRecommendationsByProductId() {

int productId = 1;

postAndVerifyRecommendation(productId, 1, OK);
postAndVerifyRecommendation(productId, 2, OK);
postAndVerifyRecommendation(productId, 3, OK);

assertEquals(3, repository.findByProductId(productId).size());

getAndVerifyRecommendationsByProductId(productId, OK)
.jsonPath("$.length()").isEqualTo(3)
.jsonPath("$[2].productId").isEqualTo(productId)
.jsonPath("$[2].recommendationId").isEqualTo(3);
}

@Test
void duplicateError() {

int productId = 1;
int recommendationId = 1;

postAndVerifyRecommendation(productId, recommendationId, OK)
.jsonPath("$.productId").isEqualTo(productId)
.jsonPath("$.recommendationId").isEqualTo(recommendationId);

assertEquals(1, repository.count());

postAndVerifyRecommendation(productId, recommendationId, UNPROCESSABLE_ENTITY)
.jsonPath("$.message").isEqualTo("Duplicate key, Product Id: 1, Recommendation Id:1");

assertEquals(1, repository.count());
}

@Test
void deleteRecommendations() {

int productId = 1;
int recommendationId = 1;

postAndVerifyRecommendation(productId, recommendationId, OK);
assertEquals(1, repository.findByProductId(productId).size());

deleteAndVerifyRecommendationsByProductId(productId, OK);
assertEquals(0, repository.findByProductId(productId).size());

deleteAndVerifyRecommendationsByProductId(productId, OK);
}

@Test
void getRecommendationsMissingParameter() {

getAndVerifyRecommendationsByProductId("", BAD_REQUEST)
.jsonPath("$.path").isEqualTo("/recommendation");
}

@Test
void getRecommendationsInvalidParameter() {

getAndVerifyRecommendationsByProductId("?productId=no-integer", BAD_REQUEST)
.jsonPath("$.path").isEqualTo("/recommendation");
}

@Test
void getRecommendationsNotFound() {

getAndVerifyRecommendationsByProductId("?productId=113", OK)
.jsonPath("$.length()").isEqualTo(0);
}

@Test
void getRecommendationsInvalidParameterNegativeValue() {

int productIdInvalid = -1;

getAndVerifyRecommendationsByProductId("?productId=" + productIdInvalid, UNPROCESSABLE_ENTITY)
.jsonPath("$.message").isEqualTo("Invalid productId: " + productIdInvalid);
}

private WebTestClient.BodyContentSpec getAndVerifyRecommendationsByProductId(int productId, HttpStatus expectedStatus) {
return getAndVerifyRecommendationsByProductId("?productId=" + productId, expectedStatus);
}

private WebTestClient.BodyContentSpec getAndVerifyRecommendationsByProductId(String productIdQuery, HttpStatus expectedStatus) {
return client.get()
.uri("/recommendation"  + productIdQuery)
.accept(APPLICATION_JSON)
.exchange()
.expectStatus().isEqualTo(expectedStatus)
.expectHeader().contentType(APPLICATION_JSON)
.expectBody();
}

private WebTestClient.BodyContentSpec postAndVerifyRecommendation(int productId, int recommendationId, HttpStatus expectedStatus) {
Recommendation recommendation = new Recommendation(productId, recommendationId, "Author " + recommendationId, recommendationId, "Content " + recommendationId, "SA");
return client.post()
.uri("/recommendation")
.body(just(recommendation), Recommendation.class)
.accept(APPLICATION_JSON)
.exchange()
.expectStatus().isEqualTo(expectedStatus)
.expectHeader().contentType(APPLICATION_JSON)
.expectBody();
}

private WebTestClient.BodyContentSpec deleteAndVerifyRecommendationsByProductId(int productId, HttpStatus expectedStatus) {
return client.delete()
.uri("/recommendation?productId=" + productId)
.accept(APPLICATION_JSON)
.exchange()
.expectStatus().isEqualTo(expectedStatus)
.expectBody();
}
}
Вопрос:
Как может возникнуть ошибка анализа шаблона для /recommendation}, если в моем коде явно используется /recommendation без фигурных скобок? Где мне искать этот призрачный узор?

Вернуться в «JAVA»