This commit is contained in:
Jonathan Cook 2020-03-03 22:15:26 +01:00
commit 878b38e667
32 changed files with 466 additions and 43 deletions

View File

@ -0,0 +1,13 @@
package com.baeldung.suppressed;
public class ExceptionalResource implements AutoCloseable {
public void processSomething() {
throw new IllegalArgumentException("Thrown from processSomething()");
}
@Override
public void close() throws Exception {
throw new NullPointerException("Thrown from close()");
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.suppressed;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class SuppressedExceptionsDemo {
public static void demoSuppressedException(String filePath) throws IOException {
FileInputStream fileIn = null;
try {
fileIn = new FileInputStream(filePath);
} catch (FileNotFoundException e) {
throw new IOException(e);
} finally {
fileIn.close();
}
}
public static void demoAddSuppressedException(String filePath) throws IOException {
Throwable firstException = null;
FileInputStream fileIn = null;
try {
fileIn = new FileInputStream(filePath);
} catch (IOException e) {
firstException = e;
} finally {
try {
fileIn.close();
} catch (NullPointerException npe) {
if (firstException != null) {
npe.addSuppressed(firstException);
}
throw npe;
}
}
}
public static void demoExceptionalResource() throws Exception {
try (ExceptionalResource exceptionalResource = new ExceptionalResource()) {
exceptionalResource.processSomething();
}
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.suppressed;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.instanceOf;
public class SuppressedExceptionsUnitTest {
@Test(expected = NullPointerException.class)
public void givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException() throws IOException {
SuppressedExceptionsDemo.demoSuppressedException("/non-existent-path/non-existent-file.txt");
}
@Test
public void givenNonExistentFileName_whenAttemptFileOpenStoreSuppressed_thenSuppressedExceptionAvailable() {
try {
SuppressedExceptionsDemo.demoAddSuppressedException("/non-existent-path/non-existent-file.txt");
} catch (Exception e) {
assertThat(e, instanceOf(NullPointerException.class));
assertEquals(1, e.getSuppressed().length);
assertThat(e.getSuppressed()[0], instanceOf(FileNotFoundException.class));
}
}
@Test
public void whenUsingExceptionalResource_thenSuppressedExceptionAvailable() {
try {
SuppressedExceptionsDemo.demoExceptionalResource();
} catch (Exception e) {
assertThat(e, instanceOf(IllegalArgumentException.class));
assertEquals("Thrown from processSomething()", e.getMessage());
assertEquals(1, e.getSuppressed().length);
assertThat(e.getSuppressed()[0], instanceOf(NullPointerException.class));
assertEquals("Thrown from close()", e.getSuppressed()[0].getMessage());
}
}
}

View File

@ -83,7 +83,6 @@
<artifactId>moshi-adapters</artifactId>
<version>${moshi.version}</version>
</dependency>
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-aspects</artifactId>
@ -95,6 +94,16 @@
<version>${aspectjrt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.takes</groupId>
<artifactId>takes</artifactId>
<version>${takes.version}</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity-engine-core.version}</version>
</dependency>
</dependencies>
<repositories>
@ -132,8 +141,55 @@
</dependencies>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>reload</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec-maven-plugin.version}</version>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.baeldung.takes.TakesApp</mainClass>
<cleanupDaemonThreads>false</cleanupDaemonThreads>
<arguments>
<argument>--port=${port}</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<jcommander.version>1.78</jcommander.version>
<lombok.version>1.18.6</lombok.version>
@ -151,5 +207,9 @@
<jcabi-maven-plugin.version>0.14.1</jcabi-maven-plugin.version>
<aspectjtools.version>1.9.2</aspectjtools.version>
<aspectjweaver.version>1.9.2</aspectjweaver.version>
<takes.version>1.19</takes.version>
<velocity-engine-core.version>2.2</velocity-engine-core.version>
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
</properties>
</project>

View File

@ -0,0 +1,42 @@
package com.baeldung.takes;
import java.io.IOException;
import java.sql.SQLException;
import org.takes.Response;
import org.takes.facets.fallback.Fallback;
import org.takes.facets.fallback.FbChain;
import org.takes.facets.fallback.FbStatus;
import org.takes.facets.fallback.RqFallback;
import org.takes.facets.fallback.TkFallback;
import org.takes.facets.fork.FkRegex;
import org.takes.facets.fork.TkFork;
import org.takes.http.Exit;
import org.takes.http.FtBasic;
import org.takes.misc.Opt;
import org.takes.rs.RsText;
public final class TakesApp {
public static void main(final String... args) throws IOException, SQLException {
new FtBasic(
new TkFallback(
new TkFork(
new FkRegex("/", new TakesHelloWorld()),
new FkRegex("/index", new TakesIndex()),
new FkRegex("/contact", new TakesContact())
),
new FbChain(
new FbStatus(404, new RsText("Page Not Found")),
new FbStatus(405, new RsText("Method Not Allowed")),
new Fallback() {
@Override
public Opt<Response> route(final RqFallback req) {
return new Opt.Single<Response>(new RsText(req.throwable().getMessage()));
}
})
), 6060
).start(Exit.NEVER);
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.takes;
import java.io.IOException;
import org.takes.Request;
import org.takes.Response;
import org.takes.Take;
import org.takes.rs.RsWithBody;
import org.takes.rs.RsWithStatus;
import org.takes.rs.RsWithType;
public final class TakesContact implements Take {
@Override
public Response act(Request req) throws IOException {
return new RsWithStatus(
new RsWithType(
new RsWithBody("Contact us at https://www.baeldung.com"),
"text/html"), 200);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.takes;
import org.takes.Request;
import org.takes.Response;
import org.takes.Take;
import org.takes.rs.RsText;
public class TakesHelloWorld implements Take {
@Override
public Response act(final Request request) {
return new RsText("Hello, world!");
}
}

View File

@ -0,0 +1,24 @@
package com.baeldung.takes;
import java.io.IOException;
import org.takes.Request;
import org.takes.Response;
import org.takes.Take;
import org.takes.rq.form.RqFormSmart;
import org.takes.rs.RsHtml;
import org.takes.rs.RsVelocity;
public final class TakesIndex implements Take {
@Override
public Response act(final Request req) throws IOException {
RqFormSmart form = new RqFormSmart(req);
String username = form.single("username");
return new RsHtml(
new RsVelocity(this.getClass().getResource("/templates/index.vm"),
new RsVelocity.Pair("username", username))
);
}
}

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Index</title>
</head>
<body>
<h1>Takes Web Application</h1>
<h2>Welcome, ${username}</h2>
</body>
</html>

View File

@ -0,0 +1,36 @@
package com.baeldung.takes;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.takes.http.FtRemote;
public class TakesAppIntegrationTest {
@Test
public void givenTake_whenRunRemoteServer_thenRespond() throws Exception {
new FtRemote(new TakesContact()).exec(
new FtRemote.Script() {
@Override
public void exec(final URI home) throws IOException {
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(new HttpGet(home));
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
assertEquals(200, statusCode);
assertEquals("Contact us at https://www.baeldung.com", result);
}
});
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.takes;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.takes.rq.RqFake;
import org.takes.rs.RsPrint;
public class TakesContactUnitTest {
@Test
public void givenTake_whenInvokeActMethod_thenRespond() throws Exception {
final String resp = new RsPrint(new TakesContact().act(new RqFake())).printBody();
assertEquals("Contact us at https://www.baeldung.com", resp);
}
}

View File

@ -53,24 +53,6 @@
</dependency>
</dependencies>
</profile>
<profile>
<id>mac-profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<file>
<exists>${java.home}/../Classes/classes.jar</exists>
</file>
</activation>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../Classes/classes.jar</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
<properties>

View File

@ -4,6 +4,8 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
@ -11,6 +13,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@ -25,6 +28,8 @@ import org.springframework.web.util.UriComponentsBuilder;
import com.baeldung.persistence.model.Foo;
import com.baeldung.persistence.service.IFooService;
import com.baeldung.web.exception.CustomException1;
import com.baeldung.web.exception.CustomException2;
import com.baeldung.web.exception.MyResourceNotFoundException;
import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
import com.baeldung.web.hateoas.event.ResourceCreatedEvent;
@ -36,6 +41,8 @@ import com.google.common.base.Preconditions;
@RequestMapping(value = "/foos")
public class FooController {
private static final Logger logger = LoggerFactory.getLogger(FooController.class);
@Autowired
private ApplicationEventPublisher eventPublisher;
@ -137,4 +144,10 @@ public class FooController {
public void delete(@PathVariable("id") final Long id) {
service.deleteById(id);
}
@ExceptionHandler({ CustomException1.class, CustomException2.class })
public void handleException(final Exception ex) {
final String error = "Application specific error handling";
logger.error(error, ex);
}
}

View File

@ -0,0 +1,73 @@
package com.baeldung.web.error;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
@Component
public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver {
private static final Logger logger = LoggerFactory.getLogger(RestResponseStatusExceptionResolver.class);
@Override
protected ModelAndView doResolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
try {
if (ex instanceof IllegalArgumentException) {
return handleIllegalArgument(
(IllegalArgumentException) ex, request, response, handler);
}
} catch (Exception handlerException) {
logger.warn("Handling of [{}] resulted in Exception", ex.getClass().getName(), handlerException);
}
return null;
}
private ModelAndView handleIllegalArgument(IllegalArgumentException ex,
final HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
final String accept = request.getHeader(HttpHeaders.ACCEPT);
response.sendError(HttpServletResponse.SC_CONFLICT);
response.setHeader("ContentType", accept);
final ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("error", prepareErrorResponse(accept));
return modelAndView;
}
/** Prepares error object based on the provided accept type.
* @param accept The Accept header present in the request.
* @return The response to return
* @throws JsonProcessingException
*/
private String prepareErrorResponse(String accept) throws JsonProcessingException {
final Map<String, String> error = new HashMap<>();
error.put("Error", "Application specific error message");
final String response;
if(MediaType.APPLICATION_JSON_VALUE.equals(accept)) {
response = new ObjectMapper().writeValueAsString(error);
} else {
response = new XmlMapper().writeValueAsString(error);
}
return response;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.web.exception;
public class CustomException1 extends RuntimeException {
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,7 @@
package com.baeldung.web.exception;
public class CustomException2 extends RuntimeException {
private static final long serialVersionUID = 1L;
}

View File

@ -1,5 +1,9 @@
package com.baeldung.web.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public final class MyResourceNotFoundException extends RuntimeException {
public MyResourceNotFoundException() {

View File

@ -10,8 +10,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.Collections;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@ -24,6 +26,7 @@ import org.springframework.test.web.servlet.MockMvc;
import com.baeldung.persistence.model.Foo;
import com.baeldung.persistence.service.IFooService;
import com.baeldung.web.controller.FooController;
import com.baeldung.web.exception.CustomException1;
import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent;
/**
@ -56,5 +59,15 @@ public class FooControllerWebLayerIntegrationTest {
.andExpect(status().isOk())
.andExpect(jsonPath("$",Matchers.hasSize(1)));
}
@Test
public void delete_forException_fromService() throws Exception {
Mockito.when(service.findAll()).thenThrow(new CustomException1());
this.mockMvc.perform(get("/foos")).andDo(h -> {
final Exception expectedException = h.getResolvedException();
Assert.assertTrue(expectedException instanceof CustomException1);
});
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.messagedriven;
package com.baeldung.ejbspringcomparison.ejb.messagedriven;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.singleton;
package com.baeldung.ejbspringcomparison.ejb.singleton;
import javax.ejb.Singleton;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.singleton;
package com.baeldung.ejbspringcomparison.ejb.singleton;
import javax.ejb.Remote;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.stateful;
package com.baeldung.ejbspringcomparison.ejb.stateful;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.stateful;
package com.baeldung.ejbspringcomparison.ejb.stateful;
import java.util.List;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.stateless;
package com.baeldung.ejbspringcomparison.ejb.stateless;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb.stateless;
package com.baeldung.ejbspringcomparison.ejb.stateless;
import javax.ejb.Remote;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.spring.config;
package com.baeldung.ejbspringcomparison.spring.config;
import javax.jms.ConnectionFactory;
@ -11,7 +11,7 @@ import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
@Configuration
@ComponentScan(basePackages = "com.baeldung.ejb.spring.comparison.spring")
@ComponentScan(basePackages = "com.baeldung.ejbspringcomparison.spring")
@EnableJms
public class ApplicationConfig {

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.spring.messagedriven;
package com.baeldung.ejbspringcomparison.spring.messagedriven;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.spring.messagedriven;
package com.baeldung.ejbspringcomparison.spring.messagedriven;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.spring.singleton;
package com.baeldung.ejbspringcomparison.spring.singleton;
import org.springframework.stereotype.Component;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.spring.stateful;
package com.baeldung.ejbspringcomparison.spring.stateful;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.ejb;
package com.baeldung.ejbspringcomparison.ejb;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -23,9 +23,9 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.baeldung.ejb.spring.comparison.ejb.singleton.CounterEJBRemote;
import com.baeldung.ejb.spring.comparison.ejb.stateful.ShoppingCartEJBRemote;
import com.baeldung.ejb.spring.comparison.ejb.stateless.FinderEJBRemote;
import com.baeldung.ejbspringcomparison.ejb.singleton.CounterEJBRemote;
import com.baeldung.ejbspringcomparison.ejb.stateful.ShoppingCartEJBRemote;
import com.baeldung.ejbspringcomparison.ejb.stateless.FinderEJBRemote;
public class EJBUnitTest {

View File

@ -1,4 +1,4 @@
package com.baeldung.ejb.spring.comparison.spring;
package com.baeldung.ejbspringcomparison.spring;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -13,10 +13,10 @@ import org.junit.ClassRule;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.baeldung.ejb.spring.comparison.spring.config.ApplicationConfig;
import com.baeldung.ejb.spring.comparison.spring.messagedriven.Producer;
import com.baeldung.ejb.spring.comparison.spring.singleton.CounterBean;
import com.baeldung.ejb.spring.comparison.spring.stateful.ShoppingCartBean;
import com.baeldung.ejbspringcomparison.spring.config.ApplicationConfig;
import com.baeldung.ejbspringcomparison.spring.messagedriven.Producer;
import com.baeldung.ejbspringcomparison.spring.singleton.CounterBean;
import com.baeldung.ejbspringcomparison.spring.stateful.ShoppingCartBean;
public class SpringUnitTest {