How can I force #AutoConfigureJsonTesters to use HAL format from spring-hateoas? - spring-boot

I have a small module that should only contain the resource model of my REST service. I want to create a test in this module to ensure that the resource model serializes and deserializes appropriate HAL format.
I have a single test and this is the configuration:
#RunWith(SpringRunner::class
#SpringBootTest
#AutoConfigureJsonTesters
class MyTest {
#Autowired
private lateinit var collectionTester: JacksonTester<Resources<Entity>>
....
}
and a very simple configuration
#SpringBootConfiguration
class TestConfig
When calling collectionTester.write on a list of Entity (which extends ResourceSupport) I don't get an _embedded field, instead I get
{"links":[],"content":[...]}
which is not HAL format.
How can I force #AutoConfigureJsonTesters to give me a JacksonTester with an ObjectMapper configured for HAL?
Spring Boot 2.0.0.RELEASE
Thanks!

The auto-configured JacksonTester will use the context’s ObjectMapper which won’t have any of the Spring HATEOAS stuff configured on it. You might be better creating a JacksonTester yourself and passing it an appropriately configured ObjectMapper to use.
I believe Spring HATEOAS has a module that it applies to the ObjectMapper to configure it. If you get stuck with that, asking in gitter/spring-projects/spring-data is probably your best bet as Spring HATEOAS is maintained by the Data team due to it being used by Spring Data REST.

Related

How to implement Spring Boot service classes without using impl and using a interface as dependency as DIP principle says?

I am trying to implement a Spring Boot REST API but I was asked to use a interface as dependency but no impl, and I don't know how to achieve this. The way I implemented was to have service classes for my entities and there I would just call the repository in my methods. I would like an example of implementation like this.
I watched some youtube tutorials but they all used impl classes
Your controller should have a field of your interface type, with the injecting annotation (in spring it's #Autowired). The DI framework will do the heavy-lifting on startup and inject the correct implementation at runtime
#Controller
public class MyController {
#Autowired
private MyInterface myInterface;
....
}
For this to work, your framework needs to recognize the concrete class. In spring you can achieve this in multiple ways - scanning package paths, xml configuration files and more.
Check the spring documentation to see which way suits you best

Sping-boot configuration-properties and service layer injection

I'm new to spring dependency-injection and am reaching out to learn about best practices. I would like to know if its a good design philosophy to inject classes annotated with #ConfigurationProperties into service layer classes (annotated with #Service). Im trying to map properties in my application.yml to a config-class as follows -
#ConstructorBinding
#ConfigurationProperties(prefix = "application")
class ApplicationConfig(
val kafka: someDeeplyNestedType = SomeDeeplyNestedObj()
) {
// helper functions
}
I'm then injecting above config class in service layer as follows -
#Service
#EnableConfigurationProperties(ApplicationConfig::class)
class RestService(val config: ApplicationConfig) {
init {
// Reference config object
// Reference application.yml properties via config object.
}
}
I'm curious to know if I can improve upon my current implementation - not sure if its agreeable to pass configuration classes to service-layer classes. I'm also curious to know if theres any better approach to wiring ApplicationConfig without needing to use EnableConfigurationProperties annotation.
It is agreeable, documented, and probably "unrivaled" (only bounded by: "limitations" (no SpEL -> helper functions!?;)).
To work with #ConfigurationProperties beans, you can inject them in the same way as any other bean, as shown in the following example:
#Service
public class MyService {
private final SomeProperties properties;
...
The only problems can arise from the "deeply", not "owning" the (config) structure ...and possibliy from "helper functions".
But
The prefix = "application" "sounds" suspicious!
Note:
[Most - almost All] (official) spring* boot properties, are already "typesafe", and have their object/class representation in spring-boot-autoconfigure packages.
Please study that "typesafe chapter", but also gazing at PropertySource Abstraction.
There is no hard rule for this as in Spring Boot we can add #EnableConfigurationProperties at a class level with stereotype annotations.
As a part of good practices EnableConfigurationProperties or any configuration thing should be part of Configuration class of or main spring boot class so any developer can easily figure out those configuration instead of going any specific service class and then check.
In your case, yo can use #EnableConfigurationProperties annotation in conjunction with #SpringBootApplication annotation.

How to make a bean discoverable by Quarkus CDI without using annotations

I have a simple Quarkus resource:
#Path("/rosters")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class RosterResource {
private final RosterService rosterService;
public RosterResource(RosterService rosterService){
this.rosterService = rosterService;
}
#GET
#Path("/{rosterId}")
public Response getRoster(#PathParam("rosterId")Long rosterId){
return Response.ok(rosterService.getRosterById(rosterId)).build();
}
}
I am trying to inject the RosterServiceinstance in my resource, but I am getting a javax.enterprise.inject.UnsatisfiedResolutionException. However, if I use the #ApplicationScoped annotation on RosterService, then everything works just fine. Is there a way of injecting the RosterService class in my resource without using annotations? In other words, is there a way of making RosterService discoverable by the Quarkus container without directly annotating the class?
Edit: looking into the CDI docs, it seems that you can manually register beans using a method with a #BuildStep annotation. However, it is not clear to me which class should contain the annotated method)
Another option would be to use a Jandex index
To the best of my knowledge, Quarkus only implements so called annotated bean discovery. That means that all CDI beans in Quarkus have to have a bean defining annotation. #ApplicationScoped is one of them.
EDIT: regarding a Jandex index, that allows you to scan for beans in additional JARs. In other words, it will only expand the set of classes that are scanned for a bean defining annotation.
When it comes to a #BuildStep method -- that is only possible in a Quarkus extension. Extensions are powerful (and indeed they can define additional beans) but also complex. You can start at https://quarkus.io/guides/building-my-first-extension, but it may feel overwhelming. It may also feel like this is not the right thing to do if you want to just make your class a bean -- and that would be true. But if your class comes from an external library that you can't change, extension makes sense.
Is there a specific reason why you don't want to annotate your service class with #ApplicationScoped (or any other of the bean discover/scope annotations)?
The only other way that I'm aware of (instead of annotations) is - as you yourself mentioned - the use of Jandex index.

Is it ok to use non-annotated classes (beans) in spring framework?

I have a spring-boot project. Some of the classes I am using it in the 'spring' way, meaning that they are annotated by "#Service", "#Repository", "#Autowired". At the same time, I have lots of classes, which are only used in the normal Java way, meaning that there are no any Spring annotations, and they are created in the standard way of constructing an object in a constructor.
For example, one of the non-annotated classes is:
public class GenericTree<T>
{
private GenericTreeNode<T> root;
public GenericTree ()
{
root = null;
}
public GenericTreeNode<T> getRoot ()
{
return this.root;
}
public void setRoot (GenericTreeNode<T> root)
{
this.root = root;
}
...
}
Is it OK or normal to have a mixure of classes with or without Spring annotations? Probably, I could convert all non-annotated classes into annotated classes by using Spring's annotation markers. Does that really benefit or is it necessary?
BTW, my application's main logic and functions are not web-centric, although they are created as a Spring project. The reason I created in Spring is I want to provide a restful service for my interface so that I can easily test in browser in development, and others can use it with Restful service.
Yes it is ok.
Keep in mind that annotations are not Spring exclusive. Annotations were introduced in Java 5 and they are just meta data for your Java code. This meta data can be useful at:
Compile time
Build time
Runtime
You can even create your own custom annotations and annotate your code with them.
Spring framework comes with some annotations and each one of them has its purpose, but that doesn't mean you have to annotate all your classes with Spring annotations when you are using this framework.
When you annotate your classes as Spring Beans, they become part of the Spring Application Context, thus making them available to be injected with the #Autowired annotation (Spring framework is based on the dependency injection design pattern). But Spring annotations have other implications too, I cannot go into the detail of each one of them but for example, you have to consider that the default scope of annotations like #Bean, #Component, #Controller, #Repository, #Service is Singleton. So whenever you annotate a class with one of these annotations and you don't define a scope, what you get is a singleton class shared all over your application. Other scopes are:
singleton
prototype
request
session
application
websocket
Taking in consideration your GenericTree class, does it make sense to annotate an abstract data structure class as a Spring Bean? Probably not.
So yes, when you develop an application based on Spring framework the normal thing is to have a mixture of Spring annotated classes and regular POJO's.
I recommend you to read the Spring framework documentation, learn what dependency injection is and the purpose and implications of the most used Spring annotations.

Spring Data Rest integration with Spring HATEOAS

From various documents and tuts, I've earned and learned following points so far:
Spring Data Rest (SDR) used for exposing our Spring Data Repository as REST service, so that one can use it for self exploring, without any need of creating JAXRS manually. It only works for Repository layer, and we cannot control its way of working in terms of modification or addition other than the configuration using RepositoryRestMvcConfiguration. It uses Spring HATEOAS internally somewhere.
Spring HATEOAS is made for creating links within Entities we return through Controller or REST endpoints. We got ResourceSupport to extend our entity or Resource wrapper class to wrap our Entity to create or add links. There are several Annotations and classes to use such as #EnableHyperediaSupport and EntityLinks.
There may be some points which I am yet to explore or get to know about, but I was just curious about How can we combine SDR into HATEOAS link building process ? Say for eg.
EntityBean bean = repository.findByName(name);
Resource<EntityBean> resource = new Resource<EntityBean>(bean);
//JaxRsLinkBuilder.linkTo(TestResource.class).withRel("entity") // this also works
//ControllerLinkBuilder.linkTo(TestResource.class).withRel("myRel") // this also works
// I am curious how ControllerLinkBuilder and JaxRSLinkBuilder both are working for JaxRS.
//Here TestResource is my REST service class. now in below line:
resource.add(JaxRsLinkBuilder.linkTo(MyRepository.class).withRel("sdf")); //not working
// MyRepository is SDR exposed repository, which I thought should work but not working.
return resource;
So, I just wanted to include my exposed REST repository into manual HATEOAS link building process.. is it possible to do so ?
You should able to use Spring-HATEOAS ResourceProcessor to build links.
Example:
#Component
public class MyBeanResourceProcessor implements ResourceProcessor<Resource<MyBean>> {
#Autowired
private EntityLinks entityLinks;
public Resource<MyBean> process(Resource<MyBean> resource) {
MyBean mybean = resource.getContent();
// Do your linking here using entity class
//EntityBean bean = repository.findByName(name);
//Resource<EntityBean> resource = new Resource<EntityBean>(bean);
// assuming you are linking to a single resource and bean.getId() method... check entitylinks for other methods
//resource.add(entityLinks.linkForSingleResource(bean.class,bean.getId()).withRel("sdf"));
return resource;
}
}

Resources