ModelMapper: CustomMap генерирует исключение NullPointer - PullRequest
0 голосов
/ 18 октября 2019

Я использую ModelMapper в своем приложении Spring Boot (Java 12) для сопоставления DatabaseEntities с DTO, которые будут использоваться для конечных точек REST.

Класс Recipe (Database Entity) содержит несколько переменных. Некоторые из них имеют собственный тип, так что они могут содержать несколько языков. Однако для конечной точки REST должен быть возвращен простой объект, который содержит только один язык. Поэтому у меня есть два подкласса: RecipeENG_DTO и RecipeGER_DTO, которые оба наследуют от своего суперкласса Recipe_DTO.

Моя цель - сопоставить объект Recipe с RecipeGER_DTO объектом

Java Code

Конечная точка REST

@Autowired
private ModelMapper modelMapper;


@GetMapping(path = "/all")
    public @ResponseBody
    List<? extends RecipeName_DTO> getAllRecipes(HttpServletRequest request) {
        Iterable<Recipe> recipes = recipeRepository.findAll();
        if (request.getHeader("Accept-Language").equals("de")) {
            return StreamSupport.stream(recipes.spliterator(), false).map(recipe -> modelMapper.map(recipe, RecipeNameGER_DTO.class)).collect(Collectors.toList());
        } else if (request.getHeader("Accept-Language").equals("en")) {
            return StreamSupport.stream(recipes.spliterator(), false).map(recipe -> modelMapper.map(recipe, RecipeNameENG_DTO.class)).collect(Collectors.toList());
        } else {
                return null;
            }
        }
    }

Класс рецепта

@Entity
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"},
        allowGetters = true)
@Getter
@Setter
public class Recipe {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "recipe_name_id")
    @JsonManagedReference
    private RecipeName recipe_name;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "method_id")
    @JsonManagedReference
    private Method method;

    private Time prep_time;
    private Time cook_time;
    private int serves;
    private String image;
    private String source;

    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<RecipeIngredient> recipeIngredients;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
            name = "recipe_categories",
            joinColumns = @JoinColumn(name = "recipe_id"),
            inverseJoinColumns = @JoinColumn(name = "category_id"))
    private List<Category> categories;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    @JsonManagedReference
    private User user_id;

    private short access;

    @Column(nullable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @CreatedDate
    private Date createdAt;

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @LastModifiedDate
    private Date updatedAt;

    public Recipe() {
        recipeIngredients = new ArrayList<>();
        categories = new ArrayList<>();
    }
}

Класс RecipeDTO

@Getter
@Setter
public class Recipe_DTO {

    private Long id;
    private String recipe_name;

    private String method;

    private Time prep_time;
    private Time cook_time;
    private int serves;
    private String image;
    private String source;
    private List<String> categories;
    private String user;

    private short access;

    private Date createdAt;
    private Date updatedAt;
}

Класс RecipeENG_DTO

@Getter
@Setter
public class RecipeENG_DTO extends Recipe_DTO{

    private List<RecipeIngredientENG_DTO> recipeIngredients;

    public RecipeENG_DTO() {
        super();
    }
}


Класс RecipeGER_DTO

@Getter
@Setter
public class RecipeGER_DTO extends Recipe_DTO {

    private List<RecipeIngredientGER_DTO> recipeIngredients;

    public RecipeGER_DTO() {
        super();
    }
}

Класс AppConfig (Конфигурация ModelMapper)

@Configuration
public class AppConfig {


    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        //modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);


        modelMapper.addMappings(new PropertyMap<RecipeIngredient, RecipeIngredientGER_DTO>() {
            @Override
            protected void configure() {
                map().setIngredient(source.getIngredient().getGer());
                map().setAmount(source.getAmount());
                map().setUnit(source.getUnit().getGer());
                map().setGroup(source.getGroup().getGer());
            }
        });

        modelMapper.addMappings(new PropertyMap<Recipe, RecipeGER_DTO>() {
            @Override
            protected void configure() {
                map().setId(source.getId());
                map().setRecipe_name(source.getRecipe_name().getGer());
                map().setMethod(source.getMethod().getGer());
                map().setPrep_time(source.getPrep_time());
                map().setCook_time(source.getCook_time());
                map().setServes(source.getServes());
                map().setImage(source.getImage());
                map().setSource(source.getSource());
                map().setCategories(source.getCategories().stream().map(Category::getGer).collect(Collectors.toList()));
                map().setUser(source.getUser_id().getName());
                map().setAccess(source.getAccess());
                map().setCreatedAt(source.getCreatedAt());
                map().setUpdatedAt(source.getUpdatedAt());
                map().setRecipeIngredients(mapAll(source.getRecipeIngredients(), RecipeIngredientGER_DTO.class));
            }
        });

        return modelMapper;
    }

}

Следующие сопоставления вызывают исключение NullPointerException

map (). SetCategories (source.getCategories (). Stream (). Map (Category :: getGer).collect (Collectors.toList ()));

map (). setUser (source.getUser_id (). getName ());

map (). setUser (source.getUser_id () .getName ());

map (). setRecipeIngredients (mapAll (source.getRecipeIngredients (), RecipeIngredientGER_DTO.class));

журнал ошибок

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'recipeEndpoints': Unsatisfied dependency expressed through field 'modelMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'modelMapper' defined in class path resource [xyz/gigler/cook/AppConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.modelmapper.ModelMapper]: Factory method 'modelMapper' threw exception; nested exception is org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Failed to configure mappings

1 error
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
    at xyz.gigler.cook.CookApplication.main(CookApplication.java:12)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'modelMapper' defined in class path resource [xyz/gigler/cook/AppConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.modelmapper.ModelMapper]: Factory method 'modelMapper' threw exception; nested exception is org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Failed to configure mappings

1 error
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1251)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1171)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 24 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.modelmapper.ModelMapper]: Factory method 'modelMapper' threw exception; nested exception is org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Failed to configure mappings

1 error
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
    ... 37 common frames omitted
Caused by: org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Failed to configure mappings

1 error
    at org.modelmapper.internal.Errors.throwConfigurationExceptionIfErrorsExist(Errors.java:241)
    at org.modelmapper.internal.ExplicitMappingBuilder.build(ExplicitMappingBuilder.java:244)
    at org.modelmapper.internal.ExplicitMappingBuilder.build(ExplicitMappingBuilder.java:96)
    at org.modelmapper.internal.TypeMapImpl.addMappings(TypeMapImpl.java:92)
    at org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:124)
    at org.modelmapper.ModelMapper.addMappings(ModelMapper.java:113)
    at xyz.gigler.cook.AppConfig.modelMapper(AppConfig.java:51)
    at xyz.gigler.cook.AppConfig$$EnhancerBySpringCGLIB$$93f5c8e.CGLIB$modelMapper$0(<generated>)
    at xyz.gigler.cook.AppConfig$$EnhancerBySpringCGLIB$$93f5c8e$$FastClassBySpringCGLIB$$c2501590.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at xyz.gigler.cook.AppConfig$$EnhancerBySpringCGLIB$$93f5c8e.modelMapper(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 38 common frames omitted
Caused by: java.lang.NullPointerException: null
    at xyz.gigler.cook.AppConfig$4.configure(AppConfig.java:63)
    at org.modelmapper.PropertyMap.configure(PropertyMap.java:389)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.modelmapper.internal.ExplicitMappingBuilder.build(ExplicitMappingBuilder.java:227)
    ... 53 common frames omitted

Process finished with exit code 0
...