Я использую Spring Boot 2.3.1 с SDR, HATEOAS, Hibernate. В моем проекте я открыл репозитории через Spring Data REST. Я уже использую SDR в другом проекте, но в этом у меня странная проблема с одним контроллером. Фактически, если я добавлю несколько пользовательских конечных точек в этот контроллер, все конечные точки по умолчанию для связанной сущности будут скрыты и больше не будут доступны.
Позвольте мне объяснить лучше. У меня есть этот объект:
@EntityListeners(TenantListener.class)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class Tenant extends AbstractEntity {
@Enumerated(value = EnumType.STRING)
@Column(nullable = false, updatable = false)
private TenantType type;
@NotBlank
@Column(nullable = false)
private String fullName;
@NotBlank
@Column(nullable = false)
private String lastName;
@NotBlank
@Column(nullable = false)
private String firstName;
@Username
@Size(min = 4, max = 16)
@Column(nullable = false, unique = true)
@ColumnTransformer(write = "LOWER(?)")
private String tenantId;
//other fields
, и это Репозиторий:
@Transactional
@IsManagementUser
public interface TenantRepository extends JpaRepository<Tenant, Long>, JpaSpecificationExecutor {
@Caching(evict = {
@CacheEvict(value = "tenants", allEntries = true),
@CacheEvict(value = "tenants#id", allEntries = true),
@CacheEvict(value = "tenants#sid", allEntries = true),
@CacheEvict(value = "tenants#exists", allEntries = true),
})
@Override
<S extends Tenant> S save(S s);
@Caching(evict = {
@CacheEvict(value = "tenants", allEntries = true),
@CacheEvict(value = "tenants#id", allEntries = true),
@CacheEvict(value = "tenants#sid", allEntries = true),
@CacheEvict(value = "tenants#exists", allEntries = true),
})
@Override
void deleteById(Long aLong);
@Caching(evict = {
@CacheEvict(value = "tenants", allEntries = true),
@CacheEvict(value = "tenants#id", allEntries = true),
@CacheEvict(value = "tenants#sid", allEntries = true),
@CacheEvict(value = "tenants#exists", allEntries = true),
})
@Modifying
void deleteByTenantId(String tenantId);
@Cacheable(cacheNames = "tenants#id")
Optional<Tenant> findByTenantId(@Param("tenantId") String tenantId);
@Cacheable(cacheNames = "tenants#sid")
@Query("SELECT sid FROM Tenant t WHERE t.tenantId=:tenantId")
String findSidByTenantId(@Param("tenantId") String tenantId);
@Cacheable(cacheNames = "tenants#exists")
@Query("SELECT case WHEN (COUNT(*) > 0) THEN true ELSE false end FROM Tenant WHERE tenantId=:tenantId")
boolean existsTenantId(@Param("tenantId") String tenantId);
@Caching(evict = {
@CacheEvict(value = "tenants", allEntries = true),
@CacheEvict(value = "tenants#id", allEntries = true),
@CacheEvict(value = "tenants#exists", allEntries = true),
})
@Modifying
@Query("UPDATE Tenant t SET t.verified=:verified, t.version=t.version+1, t.lastModifiedDate=UTC_TIMESTAMP() WHERE t.tenantId=:tenantId")
void setVerified(@Param("tenantId") String tenantId, @Param("verified") boolean verified);
@Caching(evict = {
@CacheEvict(value = "tenants", allEntries = true),
@CacheEvict(value = "tenants#id", allEntries = true),
@CacheEvict(value = "tenants#exists", allEntries = true),
})
@Modifying
@Query("UPDATE Tenant t SET t.enabled=:enabled, t.version=t.version+1, t.lastModifiedDate=UTC_TIMESTAMP() WHERE t.tenantId=:tenantId")
void setEnabled(@Param("tenantId") String tenantId, @Param("enabled") boolean enabled);
}
, и это контроллер REST:
@RepositoryRestController
@RequestMapping(path = "/api/v1")
@PreAuthorize("isAuthenticated()")
public class TenantController {
@Autowired
private LocalValidatorFactoryBean validator;
@Autowired
private TenantRepository tenantRepository;
@Autowired
private DbmsManager dbmsManager;
@Autowired
private PagedResourcesAssembler pagedResourcesAssembler;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(validator);
}
@IsManagementUser
@DeleteMapping(path = "/tenants/{id}")
public ResponseEntity<?> deleteTenant(@PathVariable("id") Long id) {
Optional<Tenant> optionalTenant = tenantRepository.findById(id);
if (optionalTenant.isPresent()) {
dbmsManager.dropTenant(optionalTenant.get().getTenantId());
}
return ResponseEntity.noContent().build();
}
}
Если я вызываю конечную точку GET http://localhost/api/v1/tenants
, Получаю весь список жильцов. Если я попытаюсь вызвать любой другой метод, например GET http://localhost/api/v1/tenants/1
или PATCH http://localhost/api/v1/tenants/1
, я получаю предупреждение в консоли:
12/07/2020 21:51:01,440 WARN http-nio-9999-exec-2 PageNotFound:209 - Request method 'GET' not supported
Если я закомментирую все конечные точки в моем TenantController, все будет работать нормально. Кажется, что независимо от того, какую конечную точку я создаю в своем контроллере, все остальные конечные точки SDR по умолчанию скрываются.
Это происходит только с этим объектом и этим контроллером, но я не вижу ничего особенного. Любой намек действительно приветствуется, чтобы понять, в чем проблема.