Mapstruct generated class not being injected by Spring in JHipster web app
Asked Answered
P

8

13

I'm developing a web app created with JHipster v2.20.0. Using Eclipse 4.5.0 WTP as IDE.

The Spring configuration is annotation based.

I've just merged this pull with our code.

When I try to run the application inside Eclipse I get this exception:

[INFO] com.app.tenancy.hibernate.MyCurrentTenantIdentifierResolver - MyCurrentTenantIdentifierResolver.getTenantId(): Couldn't find Company/Tenant for the domain inventario, stopping serving the request
[WARN] org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userManagementResource': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.app.web.rest.mapper.UserManagementMapper com.app.web.rest.UserManagementResource.userManagementMapper; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.app.web.rest.mapper.UserManagementMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) [spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
    at com.app.Application.main(Application.java:79) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.app.web.rest.mapper.UserManagementMapper com.app.web.rest.UserManagementResource.userManagementMapper; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.app.web.rest.mapper.UserManagementMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    ... 14 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.app.web.rest.mapper.UserManagementMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    ... 16 common frames omitted

This is the UserManagementMapper class:

package com.app.web.rest.mapper;

import java.util.List;
import java.util.Optional;

import javax.inject.Inject;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;

import com.app.domain.User;
import com.app.service.UserService;
import com.app.web.rest.dto.UserManagementDTO;

@Mapper(componentModel = "spring", uses = {})
public abstract class UserManagementMapper {

    @Inject
    private UserService userService;

    public abstract UserManagementDTO userToUserManagementDTO(User user);
    public abstract List<UserManagementDTO> usersToUserManagementsDTO(List<User> users);

    @Mapping(target = "createdBy", ignore=true)
    @Mapping(target = "createdDate", ignore=true)
    @Mapping(target = "lastModifiedBy", ignore=true)
    @Mapping(target = "lastModifiedDate", ignore=true)
    @Mapping(target = "persistentTokens", ignore=true)
    @Mapping(target = "resetDate", ignore=true)
    @Mapping(target = "activationKey", ignore=true)
    @Mapping(target = "resetKey", ignore=true)
    @Mapping(target = "password", ignore=true)
    public abstract User updateUserFromDto(UserManagementDTO userManagementDTO, @MappingTarget User user);



    public User userManagementDTOToUser(UserManagementDTO userManagementDTO) {
        return  Optional.ofNullable(userService.getUserWithAuthorities(userManagementDTO.getId()))
            .map(user -> this.updateUserFromDto(userManagementDTO, user))
            .orElse(null);
    }
}

This is the UserManagementResource class:

package com.app.web.rest;

import java.net.URISyntaxException;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.codahale.metrics.annotation.Timed;
import com.app.domain.User;
import com.app.repository.UserRepository;
import com.app.security.AuthoritiesConstants;
import com.app.service.UserService;
import com.app.web.rest.dto.UserManagementDTO;
import com.app.web.rest.mapper.UserManagementMapper;
import com.app.web.rest.util.PaginationUtil;

/**
 * REST controller for managing users.
 */
@RestController
@RequestMapping("/api")
public class UserManagementResource {

    private final Logger log = LoggerFactory.getLogger(UserManagementResource.class);

    @Inject
    private UserService userService;

    @Inject
    private UserRepository userRepository;

    @Autowired
    private UserManagementMapper userManagementMapper;

    /**
     * GET  /userManagement -> get all users to manage.
     */
    @RequestMapping(value = "/userManagement",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    @RolesAllowed(AuthoritiesConstants.ADMIN)
    @Transactional(readOnly = true)
    public ResponseEntity<List<UserManagementDTO>> getAll(@RequestParam(value = "page" , required = false) Integer offset,
                                                         @RequestParam(value = "per_page", required = false) Integer limit)
        throws URISyntaxException {
        Page<User> page = userRepository.findAll(PaginationUtil.generatePageRequest(offset, limit));
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/userManagement", offset, limit);
        return new ResponseEntity<>(page.getContent().stream()
                 .map(userManagementMapper::userToUserManagementDTO)
                 .collect(Collectors.toCollection(LinkedList::new)), headers, HttpStatus.OK);
    }

    /**
     * GET  /userManagement/:id -> get id user to manage.
     */
    @RequestMapping(value = "/userManagement/{id}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    @RolesAllowed(AuthoritiesConstants.ADMIN)
    @Transactional(readOnly = true)
    ResponseEntity<UserManagementDTO> getUser(@PathVariable Long id) {
       log.debug("REST request to get User to manage : {}", id);
       return  Optional.ofNullable(userService.getUserWithAuthorities(id))
               .map(userManagementMapper::userToUserManagementDTO)
               .map(userManagementDTO -> new ResponseEntity<>(
                    userManagementDTO,
                    HttpStatus.OK))
               .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * PUT  /userManagement -> Updates an existing user.
     */
    @RequestMapping(value = "/userManagement",
        method = RequestMethod.PUT,
        produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    @RolesAllowed(AuthoritiesConstants.ADMIN)
    public ResponseEntity<Void> update(@RequestBody UserManagementDTO userManagementDTO) throws URISyntaxException {
        log.debug("REST request to update User : {}", userManagementDTO);
        if (userManagementDTO.getId() == null) {
            return ResponseEntity.badRequest().header("Failure", "You cannot create a new user").build();
        }
        User user = userManagementMapper.userManagementDTOToUser(userManagementDTO);
        userRepository.save(user);
        return ResponseEntity.ok().build();
    }
}

Lastly, the pom.xml file was not changed during this merge. The application was working properly before the merge.

It's probably some newbie question, but I've lost more hours trying to solve this than performing the merge.

Thanks in advance for any help!

Produce answered 16/9, 2015 at 13:17 Comment(5)
Is the "target/generated-sources" folder linked as a source folder in Eclipse? I.e. are you sure the generated mapper implementation is on your classpath? Also I am confused by the title of your question, "Duplicated generated file..." which does not seem to match the actual question. Are you having multiple problems here?Ancona
Hey @Gunnar, thanks for the quick reply! You're right, the title of the question was wrong (I was creating another one at that time... just fixed it). The "target/generated-sources" folder was not on the source folder. I'm trying to get it working now, got another errors...Produce
@Gunnar, you're the man! Would you post an answer so I can mark it as the correct solution?Produce
If you are using maven .. you can use build-helper-maven-plugin .. to add the generated sources .. m2eclipse has a connector for it .. so the generated sources will be added automatically to your projectCyaneous
I find it working by running mvn compile ...and then starting the application.Xiphoid
A
27

You should make sure that "target/generated-sources" is linked as a source folder in Eclipse.

Ancona answered 16/9, 2015 at 19:53 Comment(2)
You map also need to remove the build directory from the project resource filters. More detailed instructions can be found here: jhipster.github.io/configuring-ide-eclipse-gradle/…Rael
Got the same problem for intellij. And this also worked for me. Don't know why, but this is not described for intellij in the official jHipster documentation.Galactopoietic
J
9

For IntelliJ (Gradle) users,

Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors -> Enable annotation processing

Make sure to assemble gradle after.

For maven User,

Build tools -> Maven -> Importing -> Generated Sources folder

Joselow answered 19/2, 2019 at 5:27 Comment(2)
Annotation processing was enabled but gradle assemble made it work for me, thanks.Bathe
This just took my whole day at work. Thank you so much. This solved my problem. :)Meryl
R
5

From the JHipster documentation page for setting up Eclipse:

Add apt generated source folder to build path

When using buildship gradles default outputfolder is filtered and not visible in your workspace. Therefore you need to remove it from eclipse’s resource filter setting.

  • Right click on your project and select Properties
  • Select Resources
  • Remove the entry build
  • Select Java Build Path
  • Click Add Folder...
  • Check the path build/generated/source/apt/main

Make sure the new source folder contains the correctly generated mapper implementations when running JHipster via eclipse.

Rael answered 11/7, 2016 at 22:11 Comment(0)
P
0

I had the same problem with my JHipster project using Gradle. In Eclipse, I linked the "build\generated\source\apt\main" directory as source folder and the problem was solved.

  1. Right click your project and go to "Properties"
  2. Go to "Java Build Path" and look for "Source" tab
  3. Click on button "Link Source..."
  4. Browse for "build\generated\source\apt\main" directory
  5. You can leave the suggested name as it is
  6. Click finish

Now you can try to run your JHipster project, inside eclipse, as a Java Application and it will probably work.

Poohpooh answered 15/6, 2016 at 16:25 Comment(0)
A
0

I started using intelliJ a few days ago. Enabling annotation processing (as suggested by Shree Krishna) works for me. it's documented on JHipster IDEA config page (https://www.jhipster.tech/configuring-ide-idea/). But the current documentation on this page is not explicit for new IntelliJ users like me.

Jhispter members should update their documentation by something more explicit like Shree Krishna's anwser (it will save lot of people from spending hours for fixing the problem).

Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors -> Enable annotation processing

Ance answered 6/11, 2019 at 19:8 Comment(0)
M
0

While not using JHipster, I encountered the same issue while using regular spring boot.

The issue was, on the maven annotation processor path plugin, I had specified the annotation configuration for the MapStruct path but still maven would give the unstaisfied dependency error. The implementation of the mapstruct mapper was being generated. Also my generated annotations folder was present on the classpath. Still no use.

The fix? It was being caused by project lombok. I had NOT used project lombok in my code, but it still ended up on my dependency tree. I specified an annotation configuration path on the pom.xml file for lombok as well, and finally, the damn thing got packaged.

Mclain answered 3/10, 2020 at 10:26 Comment(0)
C
0

I faced the same Issue post-upgrade to Intellij 2020.3

The solution here worked for me

-Djps.track.ap.dependencies=false

which should be added to File | Settings | Build, Execution, Deployment | Compiler | User-local Build process VM options field.

source : https://youtrack.jetbrains.com/issue/IDEA-250718

Cuculiform answered 16/2, 2021 at 9:44 Comment(0)
S
0

For Eclipse, install plugin m2e-apt and after make sure that "target/generated-sources" is linked as a source folder

Samira answered 11/11, 2021 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.