Rest Docs 관련 문의 드립니다
본 강의를 듣고 다른 프로젝트에 Rest Docs를 적용해보고 있는데, 적용 도중 몇가지 문의 사항이 있습니다.
1. List의 각 요소에 self 링크 넣는 방법
강의 내용중에 Page의 각 요소에 PageResourcesAssembler를 이용해서 self 링크를 넣는 내용이 있었는데, Page가 아닌 List로 리턴하는 메소드에서를 어떻게 구현해야 될까요?
2. Resource 클래스를 상속한 클래스의 리턴시 에러 발생
Resource 클래스를 상속해서 링크를 생성해주는 클래스를 만들었습니다. 그리고 그 클래스를 리턴하게 했는데, 테스트에서는 통과가 되는데 실제 API 호출을 할 때는 에러가 발생합니다. 어떤 부분이 문제인지 문의드립니다.
<에러 내용>
org.springframework.http.converter.HttpMessageConversionException: Could not instantiate JAXBContext for class [class link.myrecipes.api.common.RestResource]: Implementation of JAXB-API has not been found on module path or classpath.; nested exception is javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
at org.springframework.http.converter.xml.AbstractJaxb2HttpMessageConverter.getJaxbContext(AbstractJaxb2HttpMessageConverter.java:117) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.http.converter.xml.AbstractJaxb2HttpMessageConverter.createMarshaller(AbstractJaxb2HttpMessageConverter.java:51) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter.writeToResult(Jaxb2RootElementHttpMessageConverter.java:180) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.writeInternal(AbstractXmlHttpMessageConverter.java:84) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:293) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:225) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:278) ~[jaxb-api-2.3.1.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.java:421) ~[jaxb-api-2.3.1.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.1.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.1.jar:2.3.0]
at org.springframework.http.converter.xml.AbstractJaxb2HttpMessageConverter.getJaxbContext(AbstractJaxb2HttpMessageConverter.java:112) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
... 55 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:68) ~[spring-boot-2.1.7.RELEASE.jar:2.1.7.RELEASE]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122) ~[jaxb-api-2.3.1.jar:2.3.0]
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155) ~[jaxb-api-2.3.1.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:276) ~[jaxb-api-2.3.1.jar:2.3.0]
... 59 common frames omitted
<클래스 코드>
public class RestResource<T> extends Resource<T> {
public RestResource(T content, String key, Class<?> controllerClass, LinkType[] addLinks, String linkPrefix, Link... links) {
super(content, links);
add(linkTo(controllerClass).slash(key).withSelfRel());
List<LinkType> addLinkList = Arrays.asList(addLinks);
if (addLinkList.contains(LinkType.CREATE)) {
add(linkTo(controllerClass).withRel(linkPrefix + "-create"));
}
if (addLinkList.contains(LinkType.READ)) {
add(linkTo(controllerClass).withRel(linkPrefix + "-read"));
}
if (addLinkList.contains(LinkType.UPDATE)) {
add(linkTo(controllerClass).withRel(linkPrefix + "-update"));
}
if (addLinkList.contains(LinkType.DELETE)) {
add(linkTo(controllerClass).withRel(linkPrefix + "-delete"));
}
if (addLinkList.contains(LinkType.QUERY)) {
add(linkTo(controllerClass).withRel(linkPrefix + "-query"));
}
}
public RestResource(T content, Link... links) {
super(content, links);
}
public void addProfileLink(String profileLink) {
add(new Link(profileLink).withRel("profile"));
}
public Link selfLink() {
return getLinks("self").get(0);
}
}
답변 2
0
브라우저에서 API 요청을 할 경우 Accept 헤더를 생각하지 못했던것 같네요. Postman을 사용하여 정상 응답을 받았습니다.
1번같은 경우는 Page의 사용을 고려해봐야 할 것 같습니다.
답변 감사드립니다^^
0
1. Resouece를 List 만들고 Resource에 링크를 넣어주시면 가능하겠지만 일반 도메인 클래스의 List에는 링크를 넣어줄 곳이 없네요.
2. 요청을 웹 브라우저에서 하는 경우, 원하는 응답 타입으로 XML, HTML이 Accept 헤더에 들어갈겁니다. (기본으로) 그래서 XML로 응답을 만들어 주려고 하다보니 XML 관련 라이브러리를 찾고 있는데 그게 없어서 에러가 나고 있는거네요. 웹브라우저 말고 Postman이나 REST Client를 사용해서 Accept 헤더에 JSON으로 받겠다고 설정하고 보내보시면 잘 될겁니다. XML로 받고 싶으시면 에러메시지에서 없다고 하는 클래스 담고 있는 라이브러리를 의존성을 추가하시면 되구요.
Spring 시큐리티 관련해서 WebSecurityConfigurationAdapter
0
73
1
junit5 사용하시는 분들
0
88
1
자바 빈 스펙을 준수하는지 체크하는 테스트
0
238
2
REST API 개발 중 비즈니스 로직 적용 부분의 JSON 에러
0
243
1
스프링 부트 3버전에서의 실습
0
190
1
java.lang.AssertionError: Status
0
532
2
spring doc 관련 파일 생성 관련 배포 관련 질문 드립니다.
0
287
1
섹션2 201응답받기 부분 테스트 404에러 질문입니다
0
741
1
강의 자료가 404입니다 확인 부탁 드려요!
0
477
1
연동 DB문의
0
358
1
이벤트 Repository강의 중 Event 클래스에 private Integer Id; 위치 질문
0
505
1
(Mac) postgressql 관련하여 port kill 해도 다시 살아나는 경우
0
380
0
maven으로 생성한 docs파일(index.html)에서의 not found 오류 질문
0
621
1
테스트 오류 질문드립니다.
0
512
1
docs 요청값이 반영이 안되네요... (해결)
-1
394
1
psql 적용 후 에러
0
819
2
mvn package 시 다음과 같은 에러가 나시면
0
765
2
Event에 Account manager를 추가했으면 문서화 필요
0
274
1
2년 훨씬 전 부터 Restlet-> Talend API 로 바뀌었습니다~
1
473
1
asciidoc 추가 스니펫 에러 해결법
0
400
1
_links 는 현재 fieldWithPath 를 해주지 않아도 됩니다.
0
424
3
깃랩 처음 사용자를 위한 index.adoc raw 보는 법
0
332
1
eclipse 쓰시는 분을 위한 maven-resources-plugin 팁
0
333
1
부트 + jupiter 인 경우 설정법
0
342
1





