简体   繁体   中英

Get ClassCastException when using multiple services from spring boot restcontroller

My spring boot application have behaved pretty well until I needed to access two services from the controller. In the method CreateCompany I want to check that the user exists before I store the company in the db. The company data is received properly, as is the adminId path variable.

This works once, but if I want to insert another company for the same user, I get a ClassCastException for when I try to look up the user.

A weird thing though, is that I in a different class is using the CompanyTagService to successfully insert tags into a database. When debugging, it appears as a CompanyTagService object, while the CompanyService and UserService are proxies. This is suspicious to me, but I know to little about spring proxies to figure out anything useful from it.

What am I doing wrong?

CompanyServiceBean.java

@RestController
@RequestMapping( value="/api/company")
public class CompanyController {

    @Value( "${application.config.logo_folder}" )
    private String logoFolder;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CompanyService service;

    @Autowired
    private CompanyTagService tagService;

    @Autowired
    private UserService uService;

    @RequestMapping( 
            value="/admin/{adminId}",
            method=RequestMethod.POST, 
            consumes=MediaType.APPLICATION_JSON_VALUE, 
            produces=MediaType.APPLICATION_JSON_VALUE )
    public ResponseEntity< ? > CreateCompany( @RequestBody Company company, @PathVariable( "adminId") Long adminId ){
        Company ret = null;
        ResponseEntity< ? > resp = null;
        User u = uService.findOne( adminId ); //This is where the exception occurrs.

        if( null != u )
            logger.info( "User {} was found.", u.getFirstName() );

        logger.info( "Creating company record for admin with id {}", adminId);

        if( u == null ){
            resp = new ResponseEntity< RestResult >( new RestResult( "The user id must be set", HttpStatus.BAD_REQUEST ), HttpStatus.BAD_REQUEST );
        }
        else {
            company.setAdminId(adminId);
            try{
                ret = service.create( company );
                resp = new ResponseEntity< Company >( ret, HttpStatus.CREATED );
            }
            catch( DataIntegrityViolationException ie ){
                resp = new ResponseEntity< RestResult >( new RestResult( "Company name or org. no. was already in use", HttpStatus.BAD_REQUEST ), HttpStatus.BAD_REQUEST);
            }
            catch( Exception e ){
                resp = new ResponseEntity< RestResult >( new RestResult( "Could not create the company.", HttpStatus.INTERNAL_SERVER_ERROR ), HttpStatus.INTERNAL_SERVER_ERROR);
            }
        }

        return( resp );
    }
... Other service methods

UserServiceBean.java:

@Service
@Transactional( propagation = Propagation.SUPPORTS, readOnly = true )
public class UserServiceBean implements UserService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserRepository userRepo;

    @Override
    @CachePut( value="EntWeb", key="#result.id" )
    @Transactional( propagation = Propagation.REQUIRED, readOnly = false )
    public User create(User user) {
        User ret = null;

        if( user.getId() == null ) {
            ret = userRepo.save( user );
        }

        return( ret );
    }

    @Override
    @Cacheable( value="EntWeb", key="#id")
    public User findOne(Long id) {
        User ret = userRepo.findOne( id );

        return( ret );
    }

... Other Service methods

The error output

java.lang.ClassCastException: org.entweb.model.Company cannot be cast to org.entweb.model.User
at com.sun.proxy.$Proxy126.findOne(Unknown Source) ~[na:na]
at org.entweb.web.api.CompanyController.CreateCompany(CompanyController.java:58) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_77]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_77]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_77]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_77]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]

The only problem comes to (my) mind is cache. Namely - putting different objects into one cache. Peter confirmed that it is the problem.

To fix that... There are two ways:

  • one is to have global id, and that will make all cache calls valid, with no collisions.
  • other way is to have different cashes. Pros:
    • you don't need to change existing code,
    • you have control on caching each class.

To have it done, look at cachePut spec. Values property is the one you are using to tell which caches should be updated, and contain this particular result object. Most projects uses dot prefixes - EntWeb.users.admins - or maybe entweb.users is enough. Beauty is that you can later change it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM