【问题标题】:Spring Data Rest - Null Pointer in PersistentEntityResourceAssemblerSpring Data Rest - PersistentEntityResourceAssembler 中的空指针
【发布时间】:2015-12-27 03:54:13
【问题描述】:

我有一个问题,@RepositoryRestResource 由于空指针返回 500 错误。

我有一个名为Resource 的抽象类,它使用InheritanceType.JOINED@JsonSubTypes 提供Resource 的大约5 个子类,例如ServerResource。特定的Resource 在它加入的另一个实体中被引用时返回正常。 PagingAndSortingRepository 在代码中调用时也可以正常工作。问题是@RepositoryRestResource 为Resource 实体公开的端点在直接调用时返回500 错误(由于NPE)。

调试后发现问题出在PersistentEntityResourceAssembler:154这行。映射对象为空,因为框架无法将ServerResource.class 映射到父Resource.class。缓存是一个映射,使用.getClass()

有什么方法可以让Resource 实体的一个端点为这些单独的类型工作?这几乎看起来像一个错误。

【问题讨论】:

  • 我可以 POST 到 URL,但 GET 不起作用。

标签: spring-mvc spring-data spring-data-jpa spring-data-rest


【解决方案1】:

为了纠正这个问题,我覆盖了resourceMappings() 方法,并注入了我需要的映射。这解决了问题,现在 /resources uri 正在按预期工作。

package com.environment.config;

import java.lang.reflect.Field;
import java.util.Map;

import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.core.mapping.RepositoryResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMappings;
import org.springframework.data.rest.core.mapping.ResourceMetadata;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

import com.environment.domain.Resource;
import com.environment.util.Tuple;

@Configuration
public class RepositoryConfig extends RepositoryRestMvcConfiguration {

    @Override
    public ResourceMappings resourceMappings() {
        RepositoryResourceMappings rm = RepositoryResourceMappings)super.resourceMappings();
        try {
            Field cacheField = rm.getClass().getDeclaredField("cache");
            cacheField.setAccessible(true);
            Map<Class<?>, ResourceMetadata> cache = (Map<Class<?>, ResourceMetadata>) cacheField.get(rm);

            //Get metadata for parent object
            ResourceMetadata resourceMetadata = cache.entrySet().stream()
                .map(Tuple<Class<?>,ResourceMetadata>::new)
                .filter(t -> Resource.class.equals(t.t))
                .map(t -> t.u)
                .findFirst()
                .get();

            ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
            provider.addIncludeFilter(new AssignableTypeFilter(Resource.class));

                provider.findCandidateComponents("com/environment")
                .stream()
                .map(beanDef -> {
                    try {
                        return Class.forName(beanDef.getBeanClassName());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                })
                .filter(c -> !Resource.class.equals(c))
                .filter(c -> Resource.class.isAssignableFrom(c))
                .peek(c -> System.out.println("Mapping: " + c)
                .forEach(c -> cache.put((Class<?>) c, resourceMetadata));

        } catch (Exception e) {
            e.printStackTrace();
        }


        return rm;
    }

}

【讨论】:

    猜你喜欢
    • 2016-02-07
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 2018-04-16
    • 2019-02-03
    • 2016-10-26
    • 1970-01-01
    相关资源
    最近更新 更多