Spring mvc Spring数据Rest-PersistentEntityResourcesAssembler中的空指针
由于空指针,@RepositoryRestResource返回500错误时出现问题 我有一个名为Spring mvc Spring数据Rest-PersistentEntityResourcesAssembler中的空指针,spring-mvc,spring-data,spring-data-jpa,spring-data-rest,Spring Mvc,Spring Data,Spring Data Jpa,Spring Data Rest,由于空指针,@RepositoryRestResource返回500错误时出现问题 我有一个名为Resource的抽象类,它使用InheritanceType.JOINED和@JsonSubTypes来提供Resource的大约5个子类,例如ServerResource。特定的资源在与之关联的另一个实体中引用时返回良好。在代码中调用PagingAndSortingRepository时也可以正常工作。问题是@RepositoryRestResource为资源实体公开的端点在直接调用时返回500错
Resource
的抽象类,它使用InheritanceType.JOINED
和@JsonSubTypes
来提供Resource
的大约5个子类,例如ServerResource
。特定的资源
在与之关联的另一个实体中引用时返回良好。在代码中调用PagingAndSortingRepository时也可以正常工作。问题是@RepositoryRestResource为资源
实体公开的端点在直接调用时返回500错误(由于NPE)
调试后,我发现问题是由于行PersistentEntityResourcesEmbler:154
引起的。映射对象为空,因为框架无法将ServerResource.class
映射到父Resource.class
。缓存是一个映射,使用.getClass()
有没有什么方法可以让
资源
实体为这些单独的类型找到一个端点?这几乎像是一个bug。为了纠正这个问题,我重写了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;
}
}
package com.environment.config;
导入java.lang.reflect.Field;
导入java.util.Map;
导入org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.core.type.filter.AssignableTypeFilter;
导入org.springframework.data.rest.core.config.RepositoryRestConfiguration;
导入org.springframework.data.rest.core.mapping.RepositoryResourceMappings;
导入org.springframework.data.rest.core.mapping.ResourceMappings;
导入org.springframework.data.rest.core.mapping.ResourceMetadata;
导入org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
导入com.environment.domain.Resource;
导入com.environment.util.Tuple;
@配置
公共类RepositoryConfig扩展了RepositoryRestMvcConfiguration{
@凌驾
公共资源映射ResourceMappings(){
RepositoryResourceMappings rm=RepositoryResourceMappings)super.resourceMappings();
试一试{
字段cacheField=rm.getClass().getDeclaredField(“缓存”);
cacheField.setAccessible(true);
Map要更正此问题,我重写了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;
}
}
package com.environment.config;
导入java.lang.reflect.Field;
导入java.util.Map;
导入org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.core.type.filter.AssignableTypeFilter;
导入org.springframework.data.rest.core.config.RepositoryRestConfiguration;
导入org.springframework.data.rest.core.mapping.RepositoryResourceMappings;
导入org.springframework.data.rest.core.mapping.ResourceMappings;
导入org.springframework.data.rest.core.mapping.ResourceMetadata;
导入org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
导入com.environment.domain.Resource;
导入com.environment.util.Tuple;
@配置
公共类RepositoryConfig扩展了RepositoryRestMvcConfiguration{
@凌驾
公共资源映射ResourceMappings(){
RepositoryResourceMappings rm=RepositoryResourceMappings)super.resourceMappings();
试一试{
字段cacheField=rm.getClass().getDeclaredField(“缓存”);
cacheField.setAccessible(true);
MapI可以发布到URL,但GET不起作用。我可以发布到URL,但GET不起作用。