How to change HAL links format using Spring HATEOAS - spring

I'm building a Spring REST application using Spring HATEOAS (0.16.0.RELEASE) and I'd like the JSON links output to look like:
_links: {
self: {
href: "https://<ip>/api/policies/321"
}
}
while it renders like:
"links":
[{
"rel":"self",
"href":"http://<ip>/api/policies/321"
}]
I'm using HATEOAS Resource and ResourceAssembler.
Why do I get this format instead of the other? How can I change it?

In order to use HAL as the message format language for our RESTful
API, and enable automatic pagination, we need some configuration
changes in our applicaiton. Since Spring Data and Spring HATEOAS
already provides annotations for configuration, all we need is to add
those annotations:
#Configuration
#EnableWebMvc
#EnableSpringDataWebSupport
#EnableHypermediaSupport(type = { HypermediaType.HAL })
#ComponentScan(basePackages = {
"com.jiwhiz.rest"
})
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer c) {
c.defaultContentType(MediaTypes.HAL_JSON);
}
}
#EnableSpringDataWebSupport will add support for pagination and
#EnableHypermediaSupport(type = { HypermediaType.HAL }) will add
hypermedia support. Then we set default content type to
application/hal+json.
cite: Design and Build RESTful API with Spring HATEOAS by Yuan Ji

Make sure that your using com.fasterxml.jackson dependency instead of others like org.codehaus.jackson. For example, in a Maven pom.xml :
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.5.3</version>
</dependency>

Related

Missing Swagger documentation with Springdoc for #RepositoryRestResource

I've created annotated repository, but no Swagger definition is visible
#RepositoryRestResource(path = "InstanceUptime")
public interface InstanceUptimeRepository extends JpaRepository<InstanceUptime, Long> {
#Override
#RestResource(exported = false)
void delete(InstanceUptime entity);
}
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.6.14</version>
</dependency>
Do I need to do something more to make it working?
According to the Spring docs:
The projects that use spring-data-rest can add the following
dependency (springdoc-openapi-data-rest) in combination with the springdoc-openapi-ui
dependency.
So both dependencies should be added to the pom.xml:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.14</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.6.14</version>
</dependency>
Yes it was missing dependency. I was missing spring-data-rest.

Using Spring StateMachine in an EJB container

I'm trying to use Spring's state machine library inside of a JavaEE application running in a container to manage instances of a class named RunInfo. But I'm not sure how to integrate the two together.
I tried adding the following dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.7.2</version>
</dependency>
on spring-boot-autoconfigure and then adding the following configuration class:
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = {"com.ourdomain"})
public class StateConfiguration {}
I then wrote a simple state machine configuration:
#Configuration
#EnableStateMachine(name = "runInfoStateMachine")
public class RunInfoStateMachineConfiguration extends EnumStateMachineConfigurerAdapter<RunInfoState, RunInfoEvent> {
and state handler:
#Component
public class RunInfoStateHandler extends LifecycleObjectSupport {
// ...
#Autowired private StateMachine<RunInfoState, RunInfoEvent> stateMachine;
}
based on another project that I manage (which is a pure Spring Boot app).
The state handler is created, but the state machine reference is never injected; i.e., stateMachine in the above code is always null.
How does one integrate the Spring StateMachine framework into an EJB application?

Spring boot - springdoc custom url for swagger-ui

I need to use a specific url for Swagger-ui. I have tried to use the property "springdoc.swagger-ui.path" but it only redirects.
application.propperties:
springdoc.swagger-ui.path=/helloWorld/swagger
Url in browser: http://localhost:8181/helloWorld/swagger
but the url changes to the following when hits enter button:
http://localhost:8181/manager/swagger-ui/index.html?configUrl=/manager/swagger/swagger.json/swagger-config
the question is, how can i make the path be only http://localhost:8181/helloWorld/swagger/index.html or http://localhost:8181/helloWorld/swagger once i've hit enter (I need the word "swagger-ui" and configUrl disappear)?
I`m uisng Springdoc and even tried with springfox
Pom.xml
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.2</version>
</dependency>
application.propperties:
springdoc.api-docs.path=/helloWorld/swagger/swagger.json
springdoc.swagger-ui.path=/helloWorld/swagger
I guess it's version dependent regarding the answer.
if you're using 2.8.0 and above, you could use following dependencies:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
And create a controller which will just redirect to the main swagger page, like this:
#Controller
public class SwaggerController {
#RequestMapping("/")
public String index() {
return "redirect:swagger-ui.html";
}
}
But if you use 2.6.1 or like that you can personalize your swagger configuration java class extending WebMvcConfigurerAdapter and overwriting the addViewController, like this:
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController(MAIN_URL, SWAGGER_UI_URL).setContextRelative(true);
registry.addRedirectViewController(MAIN_URL + "/", SWAGGER_UI_URL).setContextRelative(true);
}
That's it. Both approaches used the same dependencies but with different versions.

Spring Data REST Endpoints Not Generating In Swagger UI

I've implemented a controller using #BasePathAwareController which also takes advantage of Spring Data REST (for finds to expose sort/size etc.)
along with some custom endpoints (for updates etc.). The application is working as expected and the endpoints Spring
Data REST generates are working as expected and I can see the self links appear in the responses, however, i can't see
these endpoints in Swagger UI. I can just see my custom endpoints
defined in my Controller.
According to this post I need to use Swagger 3.0.0-SNAPSHOT with #EnableSwagger2WebMvc
Here's my configurations:
My app.yml:
spring:
data:
rest:
basePath: /api/v1
My POM file:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/>
</parent>
<properties>
<springfox.swagger.version>3.0.0-SNAPSHOT</springfox.swagger.version>
</properties>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-data-rest</artifactId>
<version>${springfox.swagger.version}</version>
</dependency>
Swagger Config File:
#Configuration
#Import(SpringDataRestConfiguration.class)
#EnableSwagger2WebMvc
public class SwaggerConfig {
#Bean
public Docket api(ServletContext servletContext) {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("my.package.name"))
.paths(PathSelectors.any())
.build().apiInfo(apiEndPointsInfo());
}
private ApiInfo apiEndPointsInfo() {
return new ApiInfoBuilder().title("My App REST API's")
.description("My App REST API's")
.version("1.0").build();
}
}
My repo:
#RepositoryRestResource(exported=true, collectionResourceRel="group", path="group")
public interface GroupRepository extends JpaRepository<Group, Long>, JpaSpecificationExecutor<Group> {
}
Why can't i see the default endpoints that Spring Data REST produces?
I found the issue to my problem. I wasn't aware that Spring Data REST doesn't expose the generated endpoints under the controller package name I had specified here:
.apis(RequestHandlerSelectors.basePackage("my.package.name"))
so when I changed the above line to:
.apis(RequestHandlerSelectors.any())
and I could see the JPA respository endpoints.

Jersey setup without web.xml

I'm attempting to set up a simple REST web application that uses Jersey. In the documentation, it seems that I should be able to create my application without using a web.xml file. From the site:
JAX-RS provides a deployment agnostic abstract class Application for declaring root resource and provider classes, and root resource and provider singleton instances. A Web service may extend this class to declare root resource and provider classes.
The example that follows shows this code:
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(HelloWorldResource.class);
return s;
}
}
To me, this says that I can use an Application class to do all of my servlet setup. This seems to be the configuration that reads my resource class's annotations and sets up the correct URL handling mechanisms. Is that correct? I don't have to do any other setup?
I ask because I created the following and it didn't work (I get a 404 from localhost:8080/{context}/test):
pom.xml:
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
Application class:
#ApplicationPath("/")
public class JerseyTestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
final Set<Class<?>> classes = new HashSet<>();
classes.add(JerseyTestController.class);
return classes;
}
}
Resource class:
#Path("/test")
public class JerseyTestController
{
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getTestMsg()
{
return "It works";
}
}
Dumb. All I had to do was include the jersey-servlet jar, as prescribed by this answer.

Resources