How to expose the resourceId with Spring Data Rest - spring

I had was to expose the primary key which is annotated with #Id in entity.the ID field is only visible on the resource path, but not on the JSON body.

You can configure this using the RepositoryRestConfigurerAdapter on entity level.
#Configuration
public class ExposeEntityIdRestConfiguration extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(MyEntity.class);
}
}
Be aware that using this you are working against the principles of spring-data-rest - sdr promotes hypermedia to be able to use an API by navigating between resources using links - here your resources are identified and referenced by links and thus the ids are not needed anymore. Using ids on your client pushes the complexity of constructing links to resources to the client. And the client should not be bothered with this knowledge.

The best solution would be not to using the IDs of your entities, and use the link references the hypermedia provides.
You just need to parse your JSON accordingly to the HAL specification used by Spring Data Rest.

Related

Including tenant id in url using spring-boot and HATEOAS

I'm currently migrating a legacy multi tenant REST backend to spring-boot. All the environment is set to include the tenant ID in URL.
I've managed to do this implementing my own Rest Controller defining the class using, for example, somthing like this:
#RestController()
#RequestMapping("/*/invoices")
public class InvoiceController {
#Autowired
private InvoiceRepository invoiceRepository;
#GetMapping("/{id}")
public ResponseEntity<Invoice> findById(#PathVariable("id") Long id) {
return ResponseEntity.of(invoiceRepository.findById(id));
}
}
and capturing the tenant id using a HandlerInterceptor. This works very well.
Now, I would like to use the HATEOAS implementation and don't implement the #RestController, but I can't set any way to capture the Tenant Id and extract that part from the URL. I don't find any way to configure this for the RepositoryEntityController class.
Could anyone give me some guidance to achive this.
Thanks.
I would like to use an URL with a path like "/ten1/invoices" and use a HATEOAS RestController exported by the InvoiceRepository class.

Difference between Datafetchers and Resolvers

I am planning to implement Graphql in my spring boot application. I Googled many sites for Graphql server setup in Java and came across two ways of doing it .
One is implementing GraphQlResolver like below
public class MyResolver implements GraphQLResolver<ModelX>
and another one is by Implementing Datafetcher
Reference: https://www.graphql-java.com
#Component
public class MyDataFetcher implements DataFetcher<ModelX> {
#Override
public ModelX get(DataFetchingEnvironment environment) {
// TODO Auto-generated method stub
}
}
Please provide some information on differences in both the approaches and best among them
DataFetcher is from graphql-java library , the only GraphQL Java implementation that I known in Java world so far.
GraphQLResolver is from another library called graphql-java-tools which is built on top of graphql-java . You can think that it provides a way which allow you to build a GraphQL server in a more high level way or a way that you may find more convenient. At the end , GraphQLResolver will somehow invoke DataFetcher#get() for resolving the value for a field.
An similar analogy in Spring is that graphql-java like Servlet while graphql-java-tools like SpringMVC.
The term "resolver" is a general GraphQL term and is agnostic of any specific GraphQL implementation/framework/language. Each field in GraphQL is backed by a function called the resolver which is provided by the GraphQL server developer. In short, the resolver is the first logic hit to map any specific field to any specific response.
The Netflix DGS library is now open source (as of late 2020) and it introduced "DataFetchers". DataFetchers, in the DGS world, are simply a DGS-specific way of implementing resolvers.
Reading:
Netflix DGS Resolvers

Spring Data MongoDB eliminate POJO's

My system is a dynamic telemetry system. We have hundreds of different spiders all sending telemetry back to the SpringBoot server, Everything is dynamic, driven by json files in Mongo, including the UI. We don't build the UI, as opposed to individual teams can configure their own UI for their needs, all by editing json docs.
We have the majority of the UI running and i began the middleware piece. We are using Spring Boot for the first time along with Spring Data Mongo with several MQ listeners for events. The problem is Spring Data. I started reading the docs on it and I realized the docs do not address using it without POJO's. I have this wonderfully dynamic model that changes per user per minute if the telemetry spiders dictate, I couldn't shackle this to a POJO if I tried. Is there a way to use Spring Data with a Map?
It seems from my experiments that the big issue is there is no way to tell the CRUD routines of the repository class what collection to query without a POJO.
Are my suspicions correct in that this won't work and am I better off ditching Spring Data and using the Mongo driver directly?
I don't think you can do it without a pojo when using spring-data. The least you could do is this
public interface NoPojoRepository extends MongoRepository<DummyPojo, String> {
}
and create a dummy pojo with just id and a Map.
#Data
public class DummyPojo {
#Id
private String id;
private Map<String, Object> value;
}
Since this value field is a map, you can store pretty much anything.

JIRA Rest Service with Bandana Manager

I have a JIRA plugin that I'm developing that has a REST service. That service should be able to accept POSTed requests, unmarshall some data and store it. The seemingly suggested way to do this in JIRA is to make use of the Bandana persistence framework. According to this page, I should be able to simply define a setter that Spring should call to give me my Bandana manager.
#Path("/path")
public class SCMService {
private BandanaManager bandanaManager;
// setter called by Spring
public void setBandanaManager(BandanaManager bandanaManager) {
this.bandanaManager = bandanaManager;
}
//...More methods...
}
However, when I test this, the setter is never being called and my manager is null. I'm guessing this should be as simple as registering this service with Spring for injection somehow but I can't seem to find anything like that.
How would I get my setter called? Is there a better way to do this?
Er, I'm not sure that JIRA uses Bandana in that way, though Confluence does. You can certainly post data to a JIRA rest resource and then store it using properties tables
Something like this:
#POST
#Consumes (MediaType.APPLICATION_XML)
public Response createComponentAndIssues(#Context HttpServletRequest request, ...

Need matching class for LoggersMvcEndpoint. in spring-boot 2.1.9 release

I am upgrading my project from spring-boot 1.5.12.release to 2.1.9.release. I am unable to find LoggersMvcEndpoint (https://docs.spring.io/spring-boot/docs/1.5.12.RELEASE/api/org/springframework/boot/actuate/endpoint/mvc/LoggersMvcEndpoint.html) in latest version.
In one of my controller I had this. Can some one help me to fix this.
public class LoggerController extends CloudRestTemplate {
#Autowired
LoggersMvcEndpoint loggerAPI;
#Override
public Object getFromInternalApi(final String param) {
return StringUtils.isEmpty(param) ? loggerAPI.invoke() : loggerAPI.get(param);
}
#Override
public Object postToInternalApi(final String param, final Object request) {
return loggerAPI.set(param, (Map<String, String>) request);
}
}
As per Spring docs here
Endpoint infrastructure
Spring Boot 2 brings a brand new endpoint
infrastructure that allows you to define one or several operations in
a technology independent fashion with support for Spring MVC, Spring
WebFlux and Jersey! Spring Boot 2 will have native support for Jersey
and writing an adapter for another JAX-RS implementation should be
easy as long as there is a way to programmatically register resources.
The new #Endpoint annotation declares this type to be an endpoint with
a mandatory, unique id. As we will see later, a bunch of properties
will be automatically inferred from that. No additional code is
required to expose this endpoint at /applications/loggers or as a
org.springframework.boot:type=Endpoint,name=Loggers JMX MBean.
Refer to documentation, it will help you further
and for your info LoggersMvcEndpoint was there until 2.0.0.M3 https://docs.spring.io/spring-boot/docs/2.0.0.M3/api/org/springframework/boot/actuate/endpoint/mvc/LoggersMvcEndpoint.html however there is no reference of deprecation in subsequent version's release notes of 2.0.0.M4
https://docs.spring.io/spring-boot/docs/2.0.0.M4/api/deprecated-list.html#class

Resources