Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text eol=lf
*.bat eol=crlf

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.asciidoc text
*.adoc text
*.md text
*.css text
*.df text
*.htm text
*.html text
*.java text
*.js text
*.json text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.sh text
*.tld text
*.txt text
*.tag text
*.tagx text
*.xml text
*.yml text
*.ftl text

# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.gif binary
*.ico binary
*.jar binary
*.jpg binary
*.jpeg binary
*.png binary
*.so binary
*.war binary
*.pdf binary
*.exe binary
*.zip binary
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.*
!.github
!.gitignore
!.gitattributes
!.mvn
*.bak
*.log
Expand Down
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ You can run your application in dev mode that enables live coding using:

You can run tests from your IDE or via Maven. Simply run `./mvnw test ` or `./mvnw package`

## Tkit quarkus

Adding tkit libs to our project gives us several new features. Check the logs for example, all our business methods are now logged and timed.
The REST API now handles exceptions gracefully(as JSON response), and we get server side pagination with very little effort.
Our tests are now real integration tests with real postgres DB, and are stuitable for CI envs.

## Access your REST endpoint

Go to http://localhost:8080/animals
Expand Down
60 changes: 23 additions & 37 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,12 @@
<scope>provided</scope>
<version>4.3.1</version>
</dependency>
<!-- Json logging / Enable this if you do not use tkit-json-log -->
<!-- <dependency>-->
<!-- <groupId>io.quarkus</groupId>-->
<!-- <artifactId>quarkus-logging-json</artifactId>-->
<!-- </dependency>-->

<!-- JSON logging -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-logging-json</artifactId>
</dependency>

<!-- Lombok, which does what java should do out of the box -->
<dependency>
Expand Down Expand Up @@ -142,51 +143,36 @@
<scope>provided</scope>
</dependency>

<!-- 1000kit extensions-->
<dependency>
<groupId>org.tkit.quarkus</groupId>
<artifactId>tkit-quarkus-rest</artifactId>
<version>2.4.0</version>
</dependency>
<!-- Business method logger... -->
<dependency>
<groupId>org.tkit.quarkus</groupId>
<artifactId>tkit-quarkus-log-cdi</artifactId>
<version>1.4.5</version>
</dependency>
<!-- REST communication logger.. -->
<!--Testing -->
<dependency>
<groupId>org.tkit.quarkus</groupId>
<artifactId>tkit-quarkus-log-rs</artifactId>
<version>1.4.5</version>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<!-- Extended structured JSON logger -->
<dependency>
<groupId>org.tkit.quarkus</groupId>
<artifactId>tkit-quarkus-log-json</artifactId>
<version>1.4.5</version>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>

<!-- Component level integration tests -->
<dependency>
<groupId>org.tkit.quarkus</groupId>
<artifactId>tkit-quarkus-test</artifactId>
<version>1.12.0</version>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.15.2</version>
<scope>test</scope>
</dependency>

<!--Testing -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.15.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.15.2</version>
<scope>test</scope>
</dependency>

</dependencies>
<build>
<plugins>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.devonfw.quarkus.general.service.exception.mapper;

import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class AbstractExceptionMapper {

protected boolean exposeInternalErrorDetails = false;

@Context
UriInfo uriInfo;

protected void logError(Exception exception) {

log.error("Exception:{},URL:{},ERROR:{}", exception.getClass().getCanonicalName(), this.uriInfo.getRequestUri(),
exception.getMessage());
}

protected Response createResponse(int status, String errorCode, Exception exception) {

Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("errorCode", errorCode);
if (this.exposeInternalErrorDetails) {
jsonMap.put("message", getExposedErrorDetails(exception));
} else {
jsonMap.put("message", exception.getMessage());
}
jsonMap.put("uri", this.uriInfo.getPath());
jsonMap.put("timestamp", ZonedDateTime.now().toString());
return Response.status(status).type(MediaType.APPLICATION_JSON).entity(jsonMap).build();
}
Comment thread
GuentherJulian marked this conversation as resolved.

protected String getExposedErrorDetails(Throwable error) {

StringBuilder buffer = new StringBuilder();
Throwable e = error;
while (e != null) {
if (buffer.length() > 0) {
buffer.append(System.lineSeparator());
}
buffer.append(e.getClass().getSimpleName());
buffer.append(": ");
buffer.append(e.getLocalizedMessage());
e = e.getCause();
}
return buffer.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.devonfw.quarkus.general.service.exception.mapper;

import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class NotFoundExceptionMapper extends AbstractExceptionMapper implements ExceptionMapper<NotFoundException> {
Comment thread
maybeec marked this conversation as resolved.

@Override
public Response toResponse(NotFoundException exception) {

logError(exception);

return createResponse(Status.NOT_FOUND.getStatusCode(), exception.getClass().getSimpleName(), exception);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.devonfw.quarkus.general.service.exception.mapper;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import com.devonfw.quarkus.general.service.exception.ApplicationBusinessException;

@Provider
public class RuntimeExceptionMapper extends AbstractExceptionMapper implements ExceptionMapper<RuntimeException> {

@Override
public Response toResponse(RuntimeException exception) {

logError(exception);

if (exception instanceof ApplicationBusinessException) {
return createResponse((ApplicationBusinessException) exception);
} else if (exception instanceof WebApplicationException) {
return createResponse((WebApplicationException) exception);
}

return createResponse(exception);
}

private Response createResponse(ApplicationBusinessException exception) {

int status = exception.getStatusCode() == null ? Status.BAD_REQUEST.getStatusCode() : exception.getStatusCode();
return createResponse(status, exception.getCode(), exception);
}

private Response createResponse(WebApplicationException exception) {

Status status = Status.fromStatusCode(exception.getResponse().getStatus());
return createResponse(status.getStatusCode(), exception.getClass().getSimpleName(), exception);
}

private Response createResponse(Exception exception) {

return createResponse(Status.INTERNAL_SERVER_ERROR.getStatusCode(), exception.getClass().getSimpleName(),
exception);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.devonfw.quarkus.general.service.exception.mapper;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import io.quarkus.security.UnauthorizedException;

@Provider
public class UnauthorizedExceptionMapper extends AbstractExceptionMapper
implements ExceptionMapper<UnauthorizedException> {
Comment thread
maybeec marked this conversation as resolved.

@Override
public Response toResponse(UnauthorizedException exception) {

logError(exception);

return createResponse(Status.UNAUTHORIZED.getStatusCode(), exception.getClass().getSimpleName(), exception);
}
}
Loading