0

I'm learning and practicing CRUD Ops in which I'm trying to edit a MovieCatalogue using PATCH request but on hitting API endpoint I'm getting below ERROR!

I've R&D alot but didn't got appropriate solution

Stacktrace

2022-03-09 14:17:48.110 ERROR 15483 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Can not set com.muhammadtaha.moviecatalogue.models.MovieData field com.muhammadtaha.moviecatalogue.models.MovieCatalogue.data to java.util.LinkedHashMap] with root cause

java.lang.IllegalArgumentException: Can not set com.muhammadtaha.moviecatalogue.models.MovieData field com.muhammadtaha.moviecatalogue.models.MovieCatalogue.data to java.util.LinkedHashMap
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[na:na]
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) ~[na:na]
    at java.base/java.lang.reflect.Field.set(Field.java:799) ~[na:na]
    at org.springframework.util.ReflectionUtils.setField(ReflectionUtils.java:637) ~[spring-core-5.3.16.jar:5.3.16]
    at com.muhammadtaha.moviecatalogue.services.implimentations.MovieCatalogueServiceImpl.lambda$editInfo$0(MovieCatalogueServiceImpl.java:70) ~[classes/:na]
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na]
    at com.muhammadtaha.moviecatalogue.services.implimentations.MovieCatalogueServiceImpl.editInfo(MovieCatalogueServiceImpl.java:67) ~[classes/:na]
    at com.muhammadtaha.moviecatalogue.controllers.MovieCatalogueController.editInfo(MovieCatalogueController.java:47) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.16.jar:5.3.16]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:880) ~[spring-webmvc-5.3.16.jar:5.3.16]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.58.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.16.jar:5.3.16]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.16.jar:5.3.16]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.16.jar:5.3.16]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

Postman response

{ "timestamp": "2022-03-09T09:17:48.123+00:00", "status": 500, "error": "Internal Server Error", "path": "/movies/19" }

MovieCatalogueController.java

@PatchMapping
    public void editInfo(@RequestParam(name = "id") Long id,
                         @RequestBody Map<String, Object> fields) {
        service.editInfo(id, fields);
        log.info("movie catalogue edited {}", fields);
    }

MovieCatalogueServiceImpl.java

@Override
    public void editInfo(Long id, Map<String, Object> fields) {
        if (repository.findById(id).isPresent() && fields != null) {
            MovieCatalogue catalogue = new ObjectMapper().convertValue(fields, MovieCatalogue.class);
            fields.forEach((key, value) -> {
                Field field = ReflectionUtils.findField(MovieCatalogue.class, key);
                field.setAccessible(true);
                ReflectionUtils.setField(field, catalogue, value);
            });
            repository.save(catalogue);
        }
    }

MovieCatalogue.java

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
public class MovieCatalogue extends BaseEntity<MovieCatalogue> {

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "data_id", referencedColumnName = "id")
    private MovieData data;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "rating_id", referencedColumnName = "id")
    private Rating rating;
}

MovieData.java

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
public class MovieData extends BaseEntity<MovieData> {

    private String name;
    private String description;

    @OneToOne(mappedBy = "data")
    @JsonIgnore
    @Transient
    private MovieCatalogue movieCatalogue;
}

Rating.java

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = false)
public class Rating extends BaseEntity<Rating> {

    private Double rating;

    @OneToOne(mappedBy = "rating")
    @JsonIgnore
    @Transient
    private MovieCatalogue movieCatalogue;
}

PATCH API endpoint is

http://localhost:8080/movies/{id}

// for data persistance in Postgres
@Repository
public interface MovieCatalogueRepository extends JpaRepository<MovieCatalogue, Long> {}
Muhammad Taha
  • 137
  • 1
  • 6
  • ```Can not set com.muhammadtaha.moviecatalogue.models.MovieData field com.muhammadtaha.moviecatalogue.models.MovieCatalogue.data to java.util.LinkedHashMap```. This does tell you a lot, doesn't it? Look at the types you're using and also check the way your calling your API. Does thsi occur when calling through Java code or can you replicate the problem using curl? – geanakuch Mar 09 '22 at 10:28
  • @geanakuch bro! I haven't used LinkedHashMap! during rnd [this](https://www.baeldung.com/jackson-linkedhashmap-cannot-be-cast) seem a bit more relevant.. I think i'm not even getting close to the problem – Muhammad Taha Mar 09 '22 at 10:48
  • @geanakuch it's not even a ClassCastException – Muhammad Taha Mar 09 '22 at 10:51
  • Jackson always represents types it does not know as LinkedHashMap. You probably need to supply a deserializer which tells Jackson how to handle ```MovieData```. Usually you'd use a TypeReference https://www.baeldung.com/jackson-map – geanakuch Mar 09 '22 at 10:52
  • @geanakuch see [this](https://stackoverflow.com/questions/60914107/java-spring-boot-rest-api-patch-java-util-linkedhashmap-cannot-be-cast-to-x?noredirect=1&lq=1) – Muhammad Taha Mar 09 '22 at 11:59

0 Answers0