Skip to content

Commit

Permalink
Update auf Spring-Boot 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Oli B committed Jan 4, 2024
1 parent c182681 commit 5793726
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 176 deletions.
14 changes: 5 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<properties>

<patterntesting.version>2.3.0</patterntesting.version>
<spring-boot.version>2.7.18</spring-boot.version>
<spring-boot.version>3.0.13</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>8</java.version>
<maven.compiler.source>8</maven.compiler.source>
Expand Down Expand Up @@ -506,19 +506,15 @@
<!-- Import dependency management from Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- for REST API Doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi</artifactId>
<version>1.7.0</version>
<type>pom</type>
<scope>import</scope>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.4</version>
</dependency>

<!-- Thymeleaf + WebJars (see https://igorski.co/java/spring-boot/layout-dialect-spring-boot-2/) -->
Expand All @@ -534,7 +530,7 @@
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<artifactId>thymeleaf-spring6</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
Expand Down
4 changes: 2 additions & 2 deletions service/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Sie kann als WAR-Archive auf einem Tomcat oder anderen Servlet-Container ausgero
Als Port für die Standalone-Anwendung ist 2517 eingestellt.
Wird die Anwendung lokal gestartet, kann über

* http://localhost:2517/swagger-ui/
* http://localhost:2517/swagger-ui/#/datenpaket-controller
* http://localhost:2517/swagger-ui/index.html
* http://localhost:2517/swagger-ui/index.html#/datenpaket-controller

die Dokumentation der REST-Services unter "datenpaket-controller eingesehen werden.
Andere REST-Services, die in der Dokumentation angzeigt werden, sind Bestandteil der Spring-Booot-Anwendung.
Expand Down
7 changes: 1 addition & 6 deletions service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
Dies ist die Service-Schnittstelle zu GDV-Xport-Lib.
</description>


<dependencies>

<dependency>
Expand Down Expand Up @@ -81,11 +80,7 @@
<!-- REST API doc -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>

<!-- Thymeleaf + WebJars (see https://igorski.co/java/spring-boot/layout-dialect-spring-boot-2/) -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.Map;

Expand Down Expand Up @@ -96,7 +96,7 @@ private static void logAccess(String prefix, HttpServletRequest request, HttpSer
private static String getRequestURIwithParams(HttpServletRequest request) {
String requestURI = request.getRequestURI();
if ("/error".equals(requestURI)) {
Object errorRequestURI = request.getAttribute("javax.servlet.error.request_uri");
Object errorRequestURI = request.getAttribute("jakarta.servlet.error.request_uri");
if (errorRequestURI != null) {
LOG.debug("Request '{}' is mapped to '{}'.", requestURI, errorRequestURI);
requestURI = errorRequestURI.toString();
Expand Down
21 changes: 2 additions & 19 deletions service/src/main/java/gdv/xport/srv/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,15 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* Ueber diese Klasse wird Swagger aktiviert. Die Doku dazu stammt aus
* <a href="https://springfox.github.io/springfox/docs/current/">Springfox Reference Documentation</a>.
* Ueber diese Klasse wird Swagger aktiviert.
*
* @author oboehm
* @since 3.0 (20.02.2017)
*/
@Configuration
public class SwaggerConfig implements WebMvcConfigurer {
public class SwaggerConfig {

@Value("${application.version: application.version}")
private String version;
Expand All @@ -57,17 +53,4 @@ public OpenAPI api() {
);
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
.resourceChain(false);
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/swagger-ui/")
.setViewName("forward:" + "/swagger-ui/index.html");
}

}
20 changes: 18 additions & 2 deletions service/src/main/java/gdv/xport/srv/web/DatenpaketController.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import patterntesting.runtime.log.LogWatch;
import patterntesting.runtime.util.Converter;

import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
Expand Down Expand Up @@ -199,6 +199,22 @@ private static String readFrom(@RequestParam("uri") URI uri) throws IOException
return content;
}

@Operation(summary = "Liest das Datenpaket von der angegebenen URI und gibt es im gewuenschten Format zurueck." +
" Der Stern '*' in /Datenpaket* steht dabei fuer ein beliebiges Muster." +
" So kann z.B. auch /Datenpaket.csv als URI angegeben werden." +
" Das erleichtert das Abspeichern des Ergebnisses im Web-Browser." +
" Im Gegensatz zu v1 wird hier das Format nicht ueber den format-Parameter bestimmt," +
" sondern ueber den Content-Type (Content-Negotiation).")
@PostMapping(
path = "/v2/Datenpaket*", produces = {MediaType.TEXT_HTML_VALUE, MediaType.TEXT_XML_VALUE,
MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE, TEXT_CSV}
)
public @ResponseBody ResponseEntity<Datenpaket> importDatenpaketV2(
HttpServletRequest request) throws IOException {
String content = IOUtils.toString(request.getInputStream(), StandardCharsets.ISO_8859_1);
return getDatenpaketResponseEntity("", content, request);
}

/**
* Die Umwandlung eines Datenpakets in das gewuenschte Datenformat wird
* anhand des Accept-Headers (Content Negotiation) oder anhand des Suffixes
Expand Down Expand Up @@ -301,7 +317,7 @@ private static List<MediaType> toMediaTypes(HttpServletRequest request) {
if (StringUtils.isNotBlank(format)) {
mimeTypes.add(toMediaType(format));
}
String[] accepted = request.getHeader("accept").split(",");
String[] accepted = Objects.toString(request.getHeader("accept"), "").split(",");
for (String accept : accepted) {
mimeTypes.add(toMediaType(accept));
}
Expand Down
17 changes: 9 additions & 8 deletions service/src/main/java/gdv/xport/srv/web/ErrorDetail.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
*/
package gdv.xport.srv.web;

import com.fasterxml.jackson.databind.annotation.*;
import gdv.xport.srv.web.util.*;
import org.apache.logging.log4j.*;
import org.springframework.http.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import gdv.xport.srv.web.util.LocalDateTimeDeserializer;
import gdv.xport.srv.web.util.LocalDateTimeSerializer;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;

import javax.servlet.http.*;
import java.io.*;
import java.net.*;
import java.time.*;
import java.io.Serializable;
import java.net.URI;
import java.time.LocalDateTime;

/**
* Klasse ErrorDetail enthaelt Angaben zum Fehler und aufgetretener Exception.
Expand Down
2 changes: 1 addition & 1 deletion service/src/main/resources/templates/fragments/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<li><a href="format.html">Formatierung</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="/swagger-ui/" title="REST API-Doc"><span class="glyphicon glyphicon-book"></span></a></li>
<li><a href="/swagger-ui/index.html" title="REST API-Doc"><span class="glyphicon glyphicon-book"></span></a></li>
<li><a href="https://github.com/oboehm/gdv.xport" title="zur Projekt-Seite auf GitHub"><span class="glyphicon glyphicon-info-sign"></span></a></li>
</ul>
</div>
Expand Down
6 changes: 3 additions & 3 deletions service/src/main/resources/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ <h1>GDV.XPort-Services <span th:text="${appVersion}"></span></h1>
</p>
<p>
Die Dokumentation zu den REST-Services kann &uuml;ber das Buch-Symbol
<a href="/swagger-ui/"><span class="glyphicon glyphicon-book"></span></a> oben rechts
<a href="/swagger-ui/index.html"><span class="glyphicon glyphicon-book"></span></a> oben rechts
aufgerufen werden. Auf Wunsch und f&uuml;r die Auswertung durch
andere Programme ist sie im JSON-Format &uuml;ber
<a href="/v3/api-docs">/v3/api-docs</a> und online als
<a href="swagger-ui/">Swagger-Doku</a> abrufbar.
<a href="swagger-ui/index.html">Swagger-Doku</a> abrufbar.
</p>
<dl>
<dt>Hinweis:</dt>
<dd>
Wenn beim Aufuf der <a href="swagger-ui/">Swagger-Doku</a>
Wenn beim Aufuf der <a href="swagger-ui/index.html">Swagger-Doku</a>
ein <i>"Failed to load remote configuration"</i> kommt,
einfach <code>"/v3/api-docs"</code> im Eingabefeld eingeben und
<b>Explore</b> dr&uuml;cken.
Expand Down
4 changes: 2 additions & 2 deletions service/src/test/java/gdv/xport/srv/XPortApplicationIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.net.URI;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;


/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void testAfterCompletionWithException() {
public void testError() {
response.setStatus(404);
request.setRequestURI("/error");
request.setAttribute("javax.servlet.error.request_uri", "/gibts/net");
request.setAttribute("jakarta.servlet.error.request_uri", "/gibts/net");
interceptor.preHandle(request, response, "testError");
}

Expand Down
69 changes: 43 additions & 26 deletions service/src/test/java/gdv/xport/srv/web/AbstractControllerIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,59 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Before;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.*;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import patterntesting.runtime.log.LogWatch;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;

import static org.junit.jupiter.api.Assertions.assertNotNull;

/**
* In AbstractControllerIT sind einige Gemeinsamkeiter der verschiedenen
* ControllerIT-Klassen zusammengefasst.
*
* @author <a href="[email protected]">oliver</a>
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest
@AutoConfigureMockMvc
public abstract class AbstractControllerIT {

private static final Logger LOG = LogManager.getLogger(AbstractControllerIT.class);

@LocalServerPort
@Autowired
protected MockMvc mockMvc;

//@LocalServerPort
private int port;

@Autowired
//@Autowired
protected TestRestTemplate template;

protected URI baseURI;

/**
* REST-URI aufsetzen.
*/
@Before
@BeforeEach
public void setUp() {
this.baseURI = URI.create("http://localhost:" + port);
}

@Test
void testSetUp() {
assertNotNull(mockMvc);
}

/**
* Baut die URL zusammen und ruft den Service als GET-Request auf.
*
Expand All @@ -71,34 +85,37 @@ protected <T> ResponseEntity<T> getResponseEntityFor(String path, Class<T> type,
return exchangeResponseEntity(HttpMethod.GET, path, null, type, mediaTypes);
}

/**
* Baut die URL zusammen und ruft den Service als POST-Request auf.
*
* @param <T> Typ-Parameter
* @param path Context-Pfad der URL
* @param text Text
* @param type Typ der erwarteten Antwort
* @param mediaTypes Content-Types
* @return Antwort des abgesendeten Requests
*/
protected <T> T postResponseObjectFor(String path, T text, Class<T> type, MediaType... mediaTypes) {
ResponseEntity<T> response = exchangeResponseEntity(HttpMethod.POST, path, text, type, mediaTypes);
return response.getBody();
protected String getResponseStringFor(String path, MediaType... mediaTypes) throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(path)
.headers(createHeaders(mediaTypes)))
.andReturn();
return mvcResult.getResponse().getContentAsString();
}

protected String postResponseStringFor(String path, String text, MediaType... mediaTypes) throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(path)
.content(text)
.headers(createHeaders(mediaTypes)))
.andReturn();
return mvcResult.getResponse().getContentAsString();
}

private <T> ResponseEntity<T> exchangeResponseEntity(HttpMethod method, String path, T text, Class<T> type, MediaType[] mediaTypes) {
LogWatch watch = new LogWatch();
LOG.info("Requesting {}{}...", baseURI, path);
HttpHeaders headers = new HttpHeaders();
if (mediaTypes.length > 0) {
headers.setAccept(Arrays.asList(mediaTypes));
} else {
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
}
HttpHeaders headers = createHeaders(mediaTypes);
ResponseEntity<T> response =
template.exchange(baseURI.toString() + path, method, new HttpEntity<>(text, headers), type);
LOG.info("{}} {}{} finished with {} after {}.", method, baseURI, path, response.getStatusCode(), watch);
return response;
}

private static HttpHeaders createHeaders(MediaType[] mediaTypes) {
HttpHeaders headers = new HttpHeaders();
if (mediaTypes.length > 0) {
headers.setAccept(Arrays.asList(mediaTypes));
}
return headers;
}

}
Loading

0 comments on commit 5793726

Please sign in to comment.