Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
8251c25b6a
@ -0,0 +1,22 @@
|
|||||||
|
package com.baeldung.threadpool;
|
||||||
|
|
||||||
|
import java.util.concurrent.ForkJoinTask;
|
||||||
|
import java.util.concurrent.RecursiveTask;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class CountingTask extends RecursiveTask<Integer> {
|
||||||
|
|
||||||
|
private final TreeNode node;
|
||||||
|
|
||||||
|
public CountingTask(TreeNode node) {
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer compute() {
|
||||||
|
return node.value + node.children.stream()
|
||||||
|
.map(childNode -> new CountingTask(childNode).fork())
|
||||||
|
.collect(Collectors.summingInt(ForkJoinTask::join));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.baeldung.threadpool;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class demonstrates the usage of Guava's exiting executor services that keep the VM from hanging.
|
||||||
|
* Without the exiting executor service, the task would hang indefinitely.
|
||||||
|
* This behaviour cannot be demonstrated in JUnit tests, as JUnit kills the VM after the tests.
|
||||||
|
*/
|
||||||
|
public class ExitingExecutorServiceExample {
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
|
||||||
|
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
|
||||||
|
ExecutorService executorService = MoreExecutors.getExitingExecutorService(executor, 100, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
executorService.submit(() -> {
|
||||||
|
while (true) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.baeldung.threadpool;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class TreeNode {
|
||||||
|
|
||||||
|
int value;
|
||||||
|
|
||||||
|
Set<TreeNode> children;
|
||||||
|
|
||||||
|
public TreeNode(int value, TreeNode... children) {
|
||||||
|
this.value = value;
|
||||||
|
this.children = new HashSet<>();
|
||||||
|
this.children.addAll(Arrays.asList(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
package com.baeldung.threadpool;
|
||||||
|
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class CoreThreadPoolTest {
|
||||||
|
|
||||||
|
@Test(timeout = 1000)
|
||||||
|
public void whenCallingExecuteWithRunnable_thenRunnableIsExecuted() throws InterruptedException {
|
||||||
|
|
||||||
|
CountDownLatch lock = new CountDownLatch(1);
|
||||||
|
|
||||||
|
Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
executor.execute(() -> {
|
||||||
|
System.out.println("Hello World");
|
||||||
|
lock.countDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
lock.await(1000, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingExecutorServiceAndFuture_thenCanWaitOnFutureResult() throws InterruptedException, ExecutionException {
|
||||||
|
|
||||||
|
ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||||
|
Future<String> future = executorService.submit(() -> "Hello World");
|
||||||
|
String result = future.get();
|
||||||
|
|
||||||
|
assertEquals("Hello World", result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingFixedThreadPool_thenCoreAndMaximumThreadSizeAreTheSame() {
|
||||||
|
|
||||||
|
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
|
||||||
|
executor.submit(() -> {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
executor.submit(() -> {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
executor.submit(() -> {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(2, executor.getPoolSize());
|
||||||
|
assertEquals(1, executor.getQueue().size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingCachedThreadPool_thenPoolSizeGrowsUnbounded() {
|
||||||
|
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
|
||||||
|
executor.submit(() -> {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
executor.submit(() -> {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
executor.submit(() -> {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(3, executor.getPoolSize());
|
||||||
|
assertEquals(0, executor.getQueue().size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 1000)
|
||||||
|
public void whenUsingSingleThreadPool_thenTasksExecuteSequentially() throws InterruptedException {
|
||||||
|
|
||||||
|
CountDownLatch lock = new CountDownLatch(2);
|
||||||
|
AtomicInteger counter = new AtomicInteger();
|
||||||
|
|
||||||
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
executor.submit(() -> {
|
||||||
|
counter.set(1);
|
||||||
|
lock.countDown();
|
||||||
|
});
|
||||||
|
executor.submit(() -> {
|
||||||
|
counter.compareAndSet(1, 2);
|
||||||
|
lock.countDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
lock.await(1000, TimeUnit.MILLISECONDS);
|
||||||
|
assertEquals(2, counter.get());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 1000)
|
||||||
|
public void whenSchedulingTask_thenTaskExecutesWithinGivenPeriod() throws InterruptedException {
|
||||||
|
|
||||||
|
CountDownLatch lock = new CountDownLatch(1);
|
||||||
|
|
||||||
|
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
|
||||||
|
executor.schedule(() -> {
|
||||||
|
System.out.println("Hello World");
|
||||||
|
lock.countDown();
|
||||||
|
}, 500, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
lock.await(1000, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 1000)
|
||||||
|
public void whenSchedulingTaskWithFixedPeriod_thenTaskExecutesMultipleTimes() throws InterruptedException {
|
||||||
|
|
||||||
|
CountDownLatch lock = new CountDownLatch(3);
|
||||||
|
|
||||||
|
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
|
||||||
|
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
|
||||||
|
System.out.println("Hello World");
|
||||||
|
lock.countDown();
|
||||||
|
}, 500, 100, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
lock.await();
|
||||||
|
future.cancel(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingForkJoinPool_thenSumOfTreeElementsIsCalculatedCorrectly() {
|
||||||
|
|
||||||
|
TreeNode tree = new TreeNode(5,
|
||||||
|
new TreeNode(3), new TreeNode(2,
|
||||||
|
new TreeNode(2), new TreeNode(8)));
|
||||||
|
|
||||||
|
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
|
||||||
|
int sum = forkJoinPool.invoke(new CountingTask(tree));
|
||||||
|
|
||||||
|
assertEquals(20, sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.baeldung.threadpool;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class GuavaThreadPoolTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenExecutingTaskWithDirectExecutor_thenTheTaskIsExecutedInTheCurrentThread() {
|
||||||
|
|
||||||
|
Executor executor = MoreExecutors.directExecutor();
|
||||||
|
|
||||||
|
AtomicBoolean executed = new AtomicBoolean();
|
||||||
|
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
executed.set(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertTrue(executed.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenJoiningFuturesWithAllAsList_thenCombinedFutureCompletesAfterAllFuturesComplete() throws ExecutionException, InterruptedException {
|
||||||
|
|
||||||
|
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
|
||||||
|
|
||||||
|
ListenableFuture<String> future1 = listeningExecutorService.submit(() -> "Hello");
|
||||||
|
ListenableFuture<String> future2 = listeningExecutorService.submit(() -> "World");
|
||||||
|
|
||||||
|
String greeting = Futures.allAsList(future1, future2).get()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
|
assertEquals("Hello World", greeting);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,9 +6,15 @@
|
|||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>hystrix</artifactId>
|
<artifactId>hystrix</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
|
|
||||||
<name>hystrix</name>
|
<name>hystrix</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>1.4.0.RELEASE</version>
|
||||||
|
<relativePath></relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
||||||
<!-- General -->
|
<!-- General -->
|
||||||
@ -32,12 +38,35 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.netflix.hystrix</groupId>
|
<groupId>com.netflix.hystrix</groupId>
|
||||||
<artifactId>hystrix-core</artifactId>
|
<artifactId>hystrix-core</artifactId>
|
||||||
<version>${hystrix-core.version}</version>
|
<version>${hystrix-core.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.netflix.hystrix</groupId>
|
||||||
|
<artifactId>hystrix-metrics-event-stream</artifactId>
|
||||||
|
<version>1.3.16</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-dashboard -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>com.netflix.hystrix</groupId>
|
||||||
|
<artifactId>hystrix-dashboard</artifactId>
|
||||||
|
<version>1.4.3</version>
|
||||||
|
</dependency>-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.netflix.rxjava</groupId>
|
<groupId>com.netflix.rxjava</groupId>
|
||||||
<artifactId>rxjava-core</artifactId>
|
<artifactId>rxjava-core</artifactId>
|
||||||
@ -62,6 +91,10 @@
|
|||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
20
hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java
Normal file
20
hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.baeldung.hystrix;
|
||||||
|
|
||||||
|
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(AppConfig.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServletRegistrationBean adminServletRegistrationBean() {
|
||||||
|
return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.baeldung.hystrix;
|
||||||
|
|
||||||
|
import com.netflix.hystrix.*;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Aspect
|
||||||
|
public class HystrixAspect {
|
||||||
|
|
||||||
|
private HystrixCommand.Setter config;
|
||||||
|
private HystrixCommandProperties.Setter commandProperties;
|
||||||
|
private HystrixThreadPoolProperties.Setter threadPoolProperties;
|
||||||
|
|
||||||
|
@Around("@annotation(com.baeldung.hystrix.HystrixCircuitBreaker)")
|
||||||
|
public Object circuitBreakerAround(final ProceedingJoinPoint aJoinPoint) {
|
||||||
|
return new RemoteServiceCommand(config, aJoinPoint).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
private void setup() {
|
||||||
|
this.config = HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey));
|
||||||
|
this.config = config.andCommandKey(HystrixCommandKey.Factory.asKey(key));
|
||||||
|
|
||||||
|
this.commandProperties = HystrixCommandProperties.Setter();
|
||||||
|
this.commandProperties.withExecutionTimeoutInMilliseconds(executionTimeout);
|
||||||
|
this.commandProperties.withCircuitBreakerSleepWindowInMilliseconds(sleepWindow);
|
||||||
|
|
||||||
|
this.threadPoolProperties= HystrixThreadPoolProperties.Setter();
|
||||||
|
this.threadPoolProperties.withMaxQueueSize(maxThreadCount).withCoreSize(coreThreadCount).withMaxQueueSize(queueCount);
|
||||||
|
|
||||||
|
this.config.andCommandPropertiesDefaults(commandProperties);
|
||||||
|
this.config.andThreadPoolPropertiesDefaults(threadPoolProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RemoteServiceCommand extends HystrixCommand<String> {
|
||||||
|
|
||||||
|
private final ProceedingJoinPoint joinPoint;
|
||||||
|
|
||||||
|
RemoteServiceCommand(final Setter config, final ProceedingJoinPoint joinPoint) {
|
||||||
|
super(config);
|
||||||
|
this.joinPoint = joinPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String run() throws Exception {
|
||||||
|
try {
|
||||||
|
return (String) joinPoint.proceed();
|
||||||
|
} catch (final Throwable th) {
|
||||||
|
throw new Exception(th);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.execution.timeout}")
|
||||||
|
private int executionTimeout;
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.sleepwindow}")
|
||||||
|
private int sleepWindow;
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.threadpool.maxsize}")
|
||||||
|
private int maxThreadCount;
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.threadpool.coresize}")
|
||||||
|
private int coreThreadCount;
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.task.queue.size}")
|
||||||
|
private int queueCount;
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.group.key}")
|
||||||
|
private String groupKey;
|
||||||
|
|
||||||
|
@Value("${remoteservice.command.key}")
|
||||||
|
private String key;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.baeldung.hystrix;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface HystrixCircuitBreaker {
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.baeldung.hystrix;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HystrixController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SpringExistingClient client;
|
||||||
|
|
||||||
|
@RequestMapping("/")
|
||||||
|
public String index() throws InterruptedException{
|
||||||
|
return client.invokeRemoteService();
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
package com.baeldung.hystrix;
|
|
||||||
|
|
||||||
|
|
||||||
public class RemoteServiceSimulator {
|
|
||||||
|
|
||||||
public String checkSomething(final long timeout) throws InterruptedException {
|
|
||||||
|
|
||||||
System.out.print(String.format("Waiting %sms. ", timeout));
|
|
||||||
|
|
||||||
// to simulate a real world delay in processing.
|
|
||||||
Thread.sleep(timeout);
|
|
||||||
|
|
||||||
return "Done waiting.";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
package com.baeldung.hystrix;
|
package com.baeldung.hystrix;
|
||||||
|
|
||||||
|
|
||||||
class RemoteServiceTestSimulator {
|
public class RemoteServiceTestSimulator {
|
||||||
|
|
||||||
private long wait;
|
private long wait;
|
||||||
|
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.baeldung.hystrix;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component("springClient")
|
||||||
|
public class SpringExistingClient {
|
||||||
|
|
||||||
|
@Value("${remoteservice.timeout}")
|
||||||
|
private int remoteServiceDelay;
|
||||||
|
|
||||||
|
@HystrixCircuitBreaker
|
||||||
|
public String invokeRemoteService() throws InterruptedException{
|
||||||
|
return new RemoteServiceTestSimulator(remoteServiceDelay).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
hystrix/src/main/resources/application.properties
Normal file
8
hystrix/src/main/resources/application.properties
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
remoteservice.command.group.key=RemoteServiceGroup
|
||||||
|
remoteservice.command.key=RemoteServiceKey
|
||||||
|
remoteservice.command.execution.timeout=10000
|
||||||
|
remoteservice.command.threadpool.coresize=5
|
||||||
|
remoteservice.command.threadpool.maxsize=10
|
||||||
|
remoteservice.command.task.queue.size=5
|
||||||
|
remoteservice.command.sleepwindow=5000
|
||||||
|
remoteservice.timeout=5000
|
@ -9,13 +9,15 @@ import org.junit.Rule;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
public class HystrixTimeoutTest {
|
public class HystrixTimeoutTest {
|
||||||
|
|
||||||
private static HystrixCommand.Setter config;
|
private HystrixCommand.Setter config;
|
||||||
private static HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter();
|
private HystrixCommandProperties.Setter commandProperties ;
|
||||||
|
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
@ -23,6 +25,7 @@ public class HystrixTimeoutTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
|
commandProperties = HystrixCommandProperties.Setter();
|
||||||
config = HystrixCommand
|
config = HystrixCommand
|
||||||
.Setter
|
.Setter
|
||||||
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroup1"));
|
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroup1"));
|
||||||
@ -34,29 +37,86 @@ public class HystrixTimeoutTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenTimeoutEqualTo100_andDefaultSettings_thenReturnSuccess() throws InterruptedException {
|
public void givenServiceTimeoutEqualTo100_andDefaultSettings_thenReturnSuccess() throws InterruptedException {
|
||||||
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(100)).execute(), equalTo("Success"));
|
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(100)).execute(), equalTo("Success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenTimeoutEqualTo10000_andDefaultSettings_thenExpectHystrixRuntimeException() throws InterruptedException {
|
public void givenServiceTimeoutEqualTo10000_andDefaultSettings_thenExpectHRE() throws InterruptedException {
|
||||||
exception.expect(HystrixRuntimeException.class);
|
exception.expect(HystrixRuntimeException.class);
|
||||||
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(10_000)).execute();
|
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(10_000)).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenTimeoutEqualTo5000_andExecutionTimeoutEqualTo10000_thenReturnSuccess() throws InterruptedException {
|
public void givenServiceTimeoutEqualTo5000_andExecutionTimeoutEqualTo10000_thenReturnSuccess()
|
||||||
|
throws InterruptedException {
|
||||||
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
|
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
|
||||||
config.andCommandPropertiesDefaults(commandProperties);
|
config.andCommandPropertiesDefaults(commandProperties);
|
||||||
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(5_000)).execute(), equalTo("Success"));
|
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
|
||||||
|
equalTo("Success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenTimeoutEqualTo15000_andExecutionTimeoutEqualTo10000_thenExpectHystrixRuntimeException() throws InterruptedException {
|
public void givenServiceTimeoutEqualTo15000_andExecutionTimeoutEqualTo5000_thenExpectHRE()
|
||||||
|
throws InterruptedException {
|
||||||
exception.expect(HystrixRuntimeException.class);
|
exception.expect(HystrixRuntimeException.class);
|
||||||
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
|
commandProperties.withExecutionTimeoutInMilliseconds(5_000);
|
||||||
config.andCommandPropertiesDefaults(commandProperties);
|
config.andCommandPropertiesDefaults(commandProperties);
|
||||||
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(15_000)).execute();
|
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(15_000)).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenServiceTimeoutEqual_andExecutionTimeout_andThreadPool_thenReturnSuccess()
|
||||||
|
throws InterruptedException {
|
||||||
|
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
|
||||||
|
config.andCommandPropertiesDefaults(commandProperties);
|
||||||
|
config.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
|
||||||
|
.withMaxQueueSize(10)
|
||||||
|
.withCoreSize(3)
|
||||||
|
.withQueueSizeRejectionThreshold(10));
|
||||||
|
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
|
||||||
|
equalTo("Success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCircuitBreakerSetup_thenReturnSuccess() throws InterruptedException {
|
||||||
|
|
||||||
|
commandProperties.withExecutionTimeoutInMilliseconds(1000);
|
||||||
|
|
||||||
|
commandProperties.withCircuitBreakerSleepWindowInMilliseconds(4000);
|
||||||
|
commandProperties.withExecutionIsolationStrategy(
|
||||||
|
HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
|
||||||
|
commandProperties.withCircuitBreakerEnabled(true);
|
||||||
|
commandProperties.withCircuitBreakerRequestVolumeThreshold(1);
|
||||||
|
|
||||||
|
config.andCommandPropertiesDefaults(commandProperties);
|
||||||
|
|
||||||
|
config.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
|
||||||
|
.withMaxQueueSize(1)
|
||||||
|
.withCoreSize(1)
|
||||||
|
.withQueueSizeRejectionThreshold(1));
|
||||||
|
|
||||||
|
assertThat(this.invokeRemoteService(10000), equalTo(null));
|
||||||
|
assertThat(this.invokeRemoteService(10000), equalTo(null));
|
||||||
|
Thread.sleep(5000);
|
||||||
|
|
||||||
|
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
|
||||||
|
equalTo("Success"));
|
||||||
|
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
|
||||||
|
equalTo("Success"));
|
||||||
|
assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(),
|
||||||
|
equalTo("Success"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String invokeRemoteService(long timeout) throws InterruptedException{
|
||||||
|
String response = null;
|
||||||
|
try{
|
||||||
|
response = new RemoteServiceTestCommand(config,
|
||||||
|
new RemoteServiceTestSimulator(timeout)).execute();
|
||||||
|
}catch(HystrixRuntimeException ex){
|
||||||
|
System.out.println("ex = " + ex);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@
|
|||||||
<artifactId>hibernate-entitymanager</artifactId>
|
<artifactId>hibernate-entitymanager</artifactId>
|
||||||
<version>${hibernate.version}</version>
|
<version>${hibernate.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-ehcache</artifactId>
|
||||||
|
<version>${hibernate.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>xml-apis</groupId>
|
<groupId>xml-apis</groupId>
|
||||||
<artifactId>xml-apis</artifactId>
|
<artifactId>xml-apis</artifactId>
|
||||||
@ -50,6 +55,11 @@
|
|||||||
<artifactId>spring-data-jpa</artifactId>
|
<artifactId>spring-data-jpa</artifactId>
|
||||||
<version>${spring-data-jpa.version}</version>
|
<version>${spring-data-jpa.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<version>${h2.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- validation -->
|
<!-- validation -->
|
||||||
|
|
||||||
@ -186,6 +196,7 @@
|
|||||||
<hibernate.version>4.3.11.Final</hibernate.version>
|
<hibernate.version>4.3.11.Final</hibernate.version>
|
||||||
<mysql-connector-java.version>5.1.38</mysql-connector-java.version>
|
<mysql-connector-java.version>5.1.38</mysql-connector-java.version>
|
||||||
<spring-data-jpa.version>1.8.2.RELEASE</spring-data-jpa.version>
|
<spring-data-jpa.version>1.8.2.RELEASE</spring-data-jpa.version>
|
||||||
|
<h2.version>1.4.192</h2.version>
|
||||||
|
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
<org.slf4j.version>1.7.13</org.slf4j.version>
|
<org.slf4j.version>1.7.13</org.slf4j.version>
|
||||||
|
@ -78,6 +78,8 @@ public class PersistenceJPAConfig {
|
|||||||
final Properties hibernateProperties = new Properties();
|
final Properties hibernateProperties = new Properties();
|
||||||
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
||||||
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
||||||
|
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
|
||||||
|
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
|
||||||
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
|
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
|
||||||
return hibernateProperties;
|
return hibernateProperties;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
package org.baeldung.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||||
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
|
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@PropertySource({ "classpath:persistence-h2.properties" })
|
||||||
|
@ComponentScan({ "org.baeldung.persistence" })
|
||||||
|
@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
|
||||||
|
public class PersistenceJPAConfigL2Cache {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Environment env;
|
||||||
|
|
||||||
|
public PersistenceJPAConfigL2Cache() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
// beans
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||||
|
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||||
|
em.setDataSource(dataSource());
|
||||||
|
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
|
||||||
|
|
||||||
|
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||||
|
em.setJpaVendorAdapter(vendorAdapter);
|
||||||
|
em.setJpaProperties(additionalProperties());
|
||||||
|
|
||||||
|
return em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSource dataSource() {
|
||||||
|
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||||
|
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
|
||||||
|
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
|
||||||
|
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
|
||||||
|
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
|
||||||
|
final JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||||
|
transactionManager.setEntityManagerFactory(emf);
|
||||||
|
return transactionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
|
||||||
|
return new PersistenceExceptionTranslationPostProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Properties additionalProperties() {
|
||||||
|
final Properties hibernateProperties = new Properties();
|
||||||
|
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
||||||
|
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
||||||
|
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
|
||||||
|
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
|
||||||
|
hibernateProperties.setProperty("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
|
||||||
|
return hibernateProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,13 @@
|
|||||||
package org.baeldung.persistence.model;
|
package org.baeldung.persistence.model;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.FetchType;
|
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.GenerationType;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.JoinColumn;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
@Cacheable
|
||||||
|
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||||
public class Foo implements Serializable {
|
public class Foo implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
<props>
|
<props>
|
||||||
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
|
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
|
||||||
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
|
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
|
||||||
|
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
|
||||||
|
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
|
||||||
</props>
|
</props>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
13
spring-jpa/src/main/resources/persistence-h2.properties
Normal file
13
spring-jpa/src/main/resources/persistence-h2.properties
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# jdbc.X
|
||||||
|
jdbc.driverClassName=org.h2.Driver
|
||||||
|
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
|
||||||
|
jdbc.user=sa
|
||||||
|
# jdbc.pass=
|
||||||
|
|
||||||
|
# hibernate.X
|
||||||
|
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||||
|
hibernate.show_sql=false
|
||||||
|
hibernate.hbm2ddl.auto=create-drop
|
||||||
|
hibernate.cache.use_second_level_cache=true
|
||||||
|
hibernate.cache.use_query_cache=true
|
||||||
|
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
|
@ -9,3 +9,5 @@ jdbc.pass=tutorialmy5ql
|
|||||||
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
|
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
|
||||||
hibernate.show_sql=false
|
hibernate.show_sql=false
|
||||||
hibernate.hbm2ddl.auto=create-drop
|
hibernate.hbm2ddl.auto=create-drop
|
||||||
|
hibernate.cache.use_second_level_cache=false
|
||||||
|
hibernate.cache.use_query_cache=false
|
@ -8,3 +8,5 @@ jdbc.pass=tutorialmy5ql
|
|||||||
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
|
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
|
||||||
hibernate.show_sql=false
|
hibernate.show_sql=false
|
||||||
hibernate.hbm2ddl.auto=create-drop
|
hibernate.hbm2ddl.auto=create-drop
|
||||||
|
hibernate.cache.use_second_level_cache=false
|
||||||
|
hibernate.cache.use_query_cache=false
|
@ -1,16 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
|
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
|
||||||
<persistence-unit name="punit" >
|
<persistence-unit name="punit" >
|
||||||
<class>org.baeldung.persistence.model.Foo</class>
|
<class>org.baeldung.persistence.model.Foo</class>
|
||||||
<class>org.baeldung.persistence.model.Bar</class>
|
<class>org.baeldung.persistence.model.Bar</class>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/HIBERTEST"/>
|
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/HIBERTEST"/>
|
||||||
<property name="javax.persistence.ddl-generation" value="drop-and-create-tables"/>
|
<property name="javax.persistence.ddl-generation" value="drop-and-create-tables"/>
|
||||||
<property name="javax.persistence.logging.level" value="INFO"/>
|
<property name="javax.persistence.logging.level" value="INFO"/>
|
||||||
<property name = "hibernate.show_sql" value = "true" />
|
<property name = "hibernate.show_sql" value = "true" />
|
||||||
</properties>
|
<property name = "hibernate.cache.use_second_level_cache" value = "false" />
|
||||||
|
<property name = "hibernate.cache.use_query_cache" value = "false" />
|
||||||
</persistence-unit>
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
package org.baeldung.persistence.service;
|
||||||
|
|
||||||
|
import net.sf.ehcache.CacheManager;
|
||||||
|
import org.baeldung.config.PersistenceJPAConfigL2Cache;
|
||||||
|
import org.baeldung.persistence.model.Bar;
|
||||||
|
import org.baeldung.persistence.model.Foo;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||||
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(classes = { PersistenceJPAConfigL2Cache.class }, loader = AnnotationConfigContextLoader.class)
|
||||||
|
public class SecondLevelCacheIntegrationTest {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager entityManager;
|
||||||
|
@Autowired
|
||||||
|
private FooService fooService;
|
||||||
|
@Autowired
|
||||||
|
private PlatformTransactionManager platformTransactionManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public final void before() {
|
||||||
|
entityManager.getEntityManagerFactory().getCache().evictAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenEntityIsLoaded_thenItIsCached() {
|
||||||
|
final Foo foo = new Foo(randomAlphabetic(6));
|
||||||
|
fooService.create(foo);
|
||||||
|
fooService.findOne(foo.getId());
|
||||||
|
final int size = CacheManager.ALL_CACHE_MANAGERS.get(0)
|
||||||
|
.getCache("org.baeldung.persistence.model.Foo").getSize();
|
||||||
|
assertThat(size, greaterThan(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenBarIsUpdatedInNativeQuery_thenFoosAreNotEvicted() {
|
||||||
|
final Foo foo = new Foo(randomAlphabetic(6));
|
||||||
|
fooService.create(foo);
|
||||||
|
fooService.findOne(foo.getId());
|
||||||
|
|
||||||
|
new TransactionTemplate(platformTransactionManager).execute(status -> {
|
||||||
|
final Bar bar = new Bar(randomAlphabetic(6));
|
||||||
|
entityManager.persist(bar);
|
||||||
|
final Query nativeQuery = entityManager.createNativeQuery("update BAR set NAME = :updatedName where ID = :id");
|
||||||
|
nativeQuery.setParameter("updatedName", "newName");
|
||||||
|
nativeQuery.setParameter("id", bar.getId());
|
||||||
|
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Bar.class);
|
||||||
|
return nativeQuery.executeUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
|
final int size = CacheManager.ALL_CACHE_MANAGERS.get(0)
|
||||||
|
.getCache("org.baeldung.persistence.model.Foo").getSize();
|
||||||
|
assertThat(size, greaterThan(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenCacheableQueryIsExecuted_thenItIsCached() {
|
||||||
|
new TransactionTemplate(platformTransactionManager).execute(status -> {
|
||||||
|
return entityManager.createQuery("select f from Foo f")
|
||||||
|
.setHint("org.hibernate.cacheable", true)
|
||||||
|
.getResultList();
|
||||||
|
});
|
||||||
|
|
||||||
|
final int size = CacheManager.ALL_CACHE_MANAGERS.get(0)
|
||||||
|
.getCache("org.hibernate.cache.internal.StandardQueryCache").getSize();
|
||||||
|
assertThat(size, greaterThan(0));
|
||||||
|
}
|
||||||
|
}
|
53
spring-rest/src/main/java/org/baeldung/config/WebConfig.java
Normal file
53
spring-rest/src/main/java/org/baeldung/config/WebConfig.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package org.baeldung.config;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.baeldung.config.converter.KryoHttpMessageConverter;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
|
||||||
|
import org.springframework.oxm.xstream.XStreamMarshaller;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebMvc
|
||||||
|
@ComponentScan({ "org.baeldung.web" })
|
||||||
|
public class WebConfig extends WebMvcConfigurerAdapter {
|
||||||
|
|
||||||
|
public WebConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureMessageConverters(final List<HttpMessageConverter<?>> messageConverters) {
|
||||||
|
messageConverters.add(createXmlHttpMessageConverter());
|
||||||
|
// messageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||||
|
|
||||||
|
final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
|
||||||
|
builder.indentOutput(true).dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm"));
|
||||||
|
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
|
||||||
|
// messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
|
||||||
|
messageConverters.add(new ProtobufHttpMessageConverter());
|
||||||
|
messageConverters.add(new KryoHttpMessageConverter());
|
||||||
|
super.configureMessageConverters(messageConverters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpMessageConverter<Object> createXmlHttpMessageConverter() {
|
||||||
|
final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
|
||||||
|
|
||||||
|
final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();
|
||||||
|
xmlConverter.setMarshaller(xstreamMarshaller);
|
||||||
|
xmlConverter.setUnmarshaller(xstreamMarshaller);
|
||||||
|
|
||||||
|
return xmlConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package org.baeldung.config.converter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.baeldung.web.dto.Foo;
|
||||||
|
import org.springframework.http.HttpInputMessage;
|
||||||
|
import org.springframework.http.HttpOutputMessage;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@code HttpMessageConverter} that can read and write Kryo messages.
|
||||||
|
*/
|
||||||
|
public class KryoHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
|
||||||
|
|
||||||
|
public static final MediaType KRYO = new MediaType("application", "x-kryo");
|
||||||
|
|
||||||
|
private static final ThreadLocal<Kryo> kryoThreadLocal = new ThreadLocal<Kryo>() {
|
||||||
|
@Override
|
||||||
|
protected Kryo initialValue() {
|
||||||
|
final Kryo kryo = new Kryo();
|
||||||
|
kryo.register(Foo.class, 1);
|
||||||
|
return kryo;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public KryoHttpMessageConverter() {
|
||||||
|
super(KRYO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supports(final Class<?> clazz) {
|
||||||
|
return Object.class.isAssignableFrom(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object readInternal(final Class<? extends Object> clazz, final HttpInputMessage inputMessage) throws IOException {
|
||||||
|
final Input input = new Input(inputMessage.getBody());
|
||||||
|
return kryoThreadLocal.get().readClassAndObject(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeInternal(final Object object, final HttpOutputMessage outputMessage) throws IOException {
|
||||||
|
final Output output = new Output(outputMessage.getBody());
|
||||||
|
kryoThreadLocal.get().writeClassAndObject(output, object);
|
||||||
|
output.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MediaType getDefaultContentType(final Object object) {
|
||||||
|
return KRYO;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package org.baeldung.web.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping(value = "/ex")
|
||||||
|
public class BarMappingExamplesController {
|
||||||
|
|
||||||
|
public BarMappingExamplesController() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// with @RequestParam
|
||||||
|
|
||||||
|
@RequestMapping(value = "/bars")
|
||||||
|
@ResponseBody
|
||||||
|
public String getBarBySimplePathWithRequestParam(@RequestParam("id") final long id) {
|
||||||
|
return "Get a specific Bar with id=" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/bars", params = "id")
|
||||||
|
@ResponseBody
|
||||||
|
public String getBarBySimplePathWithExplicitRequestParam(@RequestParam("id") final long id) {
|
||||||
|
return "Get a specific Bar with id=" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/bars", params = { "id", "second" })
|
||||||
|
@ResponseBody
|
||||||
|
public String getBarBySimplePathWithExplicitRequestParams(@RequestParam("id") final long id) {
|
||||||
|
return "Get a specific Bar with id=" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// with @PathVariable
|
||||||
|
|
||||||
|
@RequestMapping(value = "/bars/{numericId:[\\d]+}")
|
||||||
|
@ResponseBody
|
||||||
|
public String getBarsBySimplePathWithPathVariable(@PathVariable final long numericId) {
|
||||||
|
return "Get a specific Bar with id=" + numericId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.baeldung.web.controller;
|
||||||
|
|
||||||
|
import org.baeldung.web.dto.Company;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class CompanyController {
|
||||||
|
|
||||||
|
@RequestMapping(value = "/companyRest", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public Company getCompanyRest() {
|
||||||
|
final Company company = new Company(1, "Xpto");
|
||||||
|
return company;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package org.baeldung.web.controller;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||||
|
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
|
||||||
|
|
||||||
|
import org.baeldung.web.dto.Foo;
|
||||||
|
import org.baeldung.web.dto.FooProtos;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class FooController {
|
||||||
|
|
||||||
|
public FooController() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
// API - read
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
|
||||||
|
@ResponseBody
|
||||||
|
public Foo findById(@PathVariable final long id) {
|
||||||
|
return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// API - write
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.PUT, value = "/foos/{id}")
|
||||||
|
@ResponseStatus(HttpStatus.OK)
|
||||||
|
@ResponseBody
|
||||||
|
public Foo updateFoo(@PathVariable("id") final String id, @RequestBody final Foo foo) {
|
||||||
|
System.out.println(foo);
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/foos/{id}", produces = { "application/x-protobuf" })
|
||||||
|
@ResponseBody
|
||||||
|
public FooProtos.Foo findProtoById(@PathVariable final long id) {
|
||||||
|
return FooProtos.Foo.newBuilder().setId(1).setName("Foo Name").build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package org.baeldung.web.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping(value = "/ex")
|
||||||
|
public class FooMappingExamplesController {
|
||||||
|
|
||||||
|
public FooMappingExamplesController() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// mapping examples
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos")
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosBySimplePath() {
|
||||||
|
return "Simple Get some Foos";
|
||||||
|
}
|
||||||
|
|
||||||
|
// with @PathVariable
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos/{id}")
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosBySimplePathWithPathVariable(@PathVariable final long id) {
|
||||||
|
return "Get a specific Foo with id=" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos/{fooid}/bar/{barid}")
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosBySimplePathWithPathVariables(@PathVariable final long fooid, @PathVariable final long barid) {
|
||||||
|
return "Get a specific Bar with id=" + barid + " from a Foo with id=" + fooid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// other HTTP verbs
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos", method = RequestMethod.POST)
|
||||||
|
@ResponseBody
|
||||||
|
public String postFoos() {
|
||||||
|
return "Post some Foos";
|
||||||
|
}
|
||||||
|
|
||||||
|
// with headers
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos", headers = "key=val")
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosWithHeader() {
|
||||||
|
return "Get some Foos with Header";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos", headers = { "key1=val1", "key2=val2" })
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosWithHeaders() {
|
||||||
|
return "Get some Foos with Header";
|
||||||
|
}
|
||||||
|
|
||||||
|
// @RequestMapping(value = "/foos", method = RequestMethod.GET, headers = "Accept=application/json")
|
||||||
|
// @ResponseBody
|
||||||
|
// public String getFoosAsJsonFromBrowser() {
|
||||||
|
// return "Get some Foos with Header Old";
|
||||||
|
// }
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos", produces = { "application/json", "application/xml" })
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosAsJsonFromREST() {
|
||||||
|
return "Get some Foos with Header New";
|
||||||
|
}
|
||||||
|
|
||||||
|
// advanced - multiple mappings
|
||||||
|
|
||||||
|
@RequestMapping(value = { "/advanced/bars", "/advanced/foos" })
|
||||||
|
@ResponseBody
|
||||||
|
public String getFoosOrBarsByPath() {
|
||||||
|
return "Advanced - Get some Foos or Bars";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "*")
|
||||||
|
@ResponseBody
|
||||||
|
public String getFallback() {
|
||||||
|
return "Fallback for GET Requests";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "*", method = { RequestMethod.GET, RequestMethod.POST })
|
||||||
|
@ResponseBody
|
||||||
|
public String allFallback() {
|
||||||
|
return "Fallback for All Requests";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/foos/multiple", method = { RequestMethod.PUT, RequestMethod.POST })
|
||||||
|
@ResponseBody
|
||||||
|
public String putAndPostFoos() {
|
||||||
|
return "Advanced - PUT and POST within single method";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package org.baeldung.web.controller;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.baeldung.web.dto.Item;
|
||||||
|
import org.baeldung.web.dto.ItemManager;
|
||||||
|
import org.baeldung.web.dto.Views;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class ItemController {
|
||||||
|
|
||||||
|
@JsonView(Views.Public.class)
|
||||||
|
@RequestMapping("/items/{id}")
|
||||||
|
public Item getItemPublic(@PathVariable final int id) {
|
||||||
|
return ItemManager.getById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonView(Views.Internal.class)
|
||||||
|
@RequestMapping("/items/internal/{id}")
|
||||||
|
public Item getItemInternal(@PathVariable final int id) {
|
||||||
|
return ItemManager.getById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/date")
|
||||||
|
public Date getCurrentDate() {
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.baeldung.web.controller;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.baeldung.web.dto.Foo;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
// used to test HttpClientPostingTest
|
||||||
|
@RestController
|
||||||
|
public class SimplePostController {
|
||||||
|
|
||||||
|
@RequestMapping(value = "/users", method = RequestMethod.POST)
|
||||||
|
public String postUser(@RequestParam final String username, @RequestParam final String password) {
|
||||||
|
return "Success" + username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/users/detail", method = RequestMethod.POST)
|
||||||
|
public String postUserDetail(@RequestBody final Foo entity) {
|
||||||
|
return "Success" + entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/users/multipart", method = RequestMethod.POST)
|
||||||
|
public String uploadFile(@RequestParam final String username, @RequestParam final String password, @RequestParam("file") final MultipartFile file) {
|
||||||
|
if (!file.isEmpty()) {
|
||||||
|
try {
|
||||||
|
final DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
|
||||||
|
final String fileName = dateFormat.format(new Date());
|
||||||
|
final File fileServer = new File(fileName);
|
||||||
|
fileServer.createNewFile();
|
||||||
|
final byte[] bytes = file.getBytes();
|
||||||
|
final BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fileServer));
|
||||||
|
stream.write(bytes);
|
||||||
|
stream.close();
|
||||||
|
return "You successfully uploaded " + username;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
return "You failed to upload " + e.getMessage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "You failed to upload because the file was empty.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/users/upload", method = RequestMethod.POST)
|
||||||
|
public String postMultipart(@RequestParam("file") final MultipartFile file) {
|
||||||
|
if (!file.isEmpty()) {
|
||||||
|
try {
|
||||||
|
final DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
|
||||||
|
final String fileName = dateFormat.format(new Date());
|
||||||
|
final File fileServer = new File(fileName);
|
||||||
|
fileServer.createNewFile();
|
||||||
|
final byte[] bytes = file.getBytes();
|
||||||
|
final BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fileServer));
|
||||||
|
stream.write(bytes);
|
||||||
|
stream.close();
|
||||||
|
return "You successfully uploaded ";
|
||||||
|
} catch (final Exception e) {
|
||||||
|
return "You failed to upload " + e.getMessage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "You failed to upload because the file was empty.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.baeldung.web.controller.advice;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
|
||||||
|
|
||||||
|
@ControllerAdvice
|
||||||
|
public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice {
|
||||||
|
|
||||||
|
public JsonpControllerAdvice() {
|
||||||
|
super("callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.baeldung.web.controller.redirect;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
import org.springframework.web.servlet.view.RedirectView;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/")
|
||||||
|
public class RedirectController {
|
||||||
|
|
||||||
|
@RequestMapping(value = "/redirectWithXMLConfig", method = RequestMethod.GET)
|
||||||
|
public ModelAndView redirectWithUsingXMLConfig(final ModelMap model) {
|
||||||
|
model.addAttribute("attribute", "redirectWithXMLConfig");
|
||||||
|
return new ModelAndView("RedirectedUrl", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/redirectWithRedirectPrefix", method = RequestMethod.GET)
|
||||||
|
public ModelAndView redirectWithUsingRedirectPrefix(final ModelMap model) {
|
||||||
|
model.addAttribute("attribute", "redirectWithRedirectPrefix");
|
||||||
|
return new ModelAndView("redirect:/redirectedUrl", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/redirectWithRedirectAttributes", method = RequestMethod.GET)
|
||||||
|
public RedirectView redirectWithRedirectAttributes(final RedirectAttributes redirectAttributes) {
|
||||||
|
redirectAttributes.addFlashAttribute("flashAttribute", "redirectWithRedirectAttributes");
|
||||||
|
redirectAttributes.addAttribute("attribute", "redirectWithRedirectAttributes");
|
||||||
|
return new RedirectView("redirectedUrl");
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/redirectWithRedirectView", method = RequestMethod.GET)
|
||||||
|
public RedirectView redirectWithUsingRedirectView(final ModelMap model) {
|
||||||
|
model.addAttribute("attribute", "redirectWithRedirectView");
|
||||||
|
return new RedirectView("redirectedUrl");
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/forwardWithForwardPrefix", method = RequestMethod.GET)
|
||||||
|
public ModelAndView forwardWithUsingForwardPrefix(final ModelMap model) {
|
||||||
|
model.addAttribute("attribute", "redirectWithForwardPrefix");
|
||||||
|
return new ModelAndView("forward:/redirectedUrl", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/redirectedUrl", method = RequestMethod.GET)
|
||||||
|
public ModelAndView redirection(final ModelMap model, @ModelAttribute("flashAttribute") final Object flashAttribute) {
|
||||||
|
model.addAttribute("redirectionAttribute", flashAttribute);
|
||||||
|
return new ModelAndView("redirection", model);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package org.baeldung.web.controller.status;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ExampleController {
|
||||||
|
|
||||||
|
@RequestMapping(value = "/controller", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity sendViaResponseEntity() {
|
||||||
|
return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/exception", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity sendViaException() {
|
||||||
|
throw new ForbiddenException();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.baeldung.web.controller.status;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(value = HttpStatus.FORBIDDEN, reason="To show an example of a custom message")
|
||||||
|
public class ForbiddenException extends RuntimeException {
|
||||||
|
|
||||||
|
}
|
38
spring-rest/src/main/java/org/baeldung/web/dto/Company.java
Normal file
38
spring-rest/src/main/java/org/baeldung/web/dto/Company.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package org.baeldung.web.dto;
|
||||||
|
|
||||||
|
public class Company {
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Company() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Company(final long id, final String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Company [id=" + id + ", name=" + name + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
spring-rest/src/main/java/org/baeldung/web/dto/Foo.java
Normal file
39
spring-rest/src/main/java/org/baeldung/web/dto/Foo.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package org.baeldung.web.dto;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||||
|
|
||||||
|
@XStreamAlias("Foo")
|
||||||
|
public class Foo {
|
||||||
|
private long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Foo() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Foo(final long id, final String name) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(final long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
620
spring-rest/src/main/java/org/baeldung/web/dto/FooProtos.java
Normal file
620
spring-rest/src/main/java/org/baeldung/web/dto/FooProtos.java
Normal file
@ -0,0 +1,620 @@
|
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
// source: FooProtos.proto
|
||||||
|
|
||||||
|
package org.baeldung.web.dto;
|
||||||
|
|
||||||
|
public final class FooProtos {
|
||||||
|
private FooProtos() {}
|
||||||
|
public static void registerAllExtensions(
|
||||||
|
com.google.protobuf.ExtensionRegistry registry) {
|
||||||
|
}
|
||||||
|
public interface FooOrBuilder extends
|
||||||
|
// @@protoc_insertion_point(interface_extends:baeldung.Foo)
|
||||||
|
com.google.protobuf.MessageOrBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
boolean hasId();
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
long getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
boolean hasName();
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
java.lang.String getName();
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
com.google.protobuf.ByteString
|
||||||
|
getNameBytes();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Protobuf type {@code baeldung.Foo}
|
||||||
|
*/
|
||||||
|
public static final class Foo extends
|
||||||
|
com.google.protobuf.GeneratedMessage implements
|
||||||
|
// @@protoc_insertion_point(message_implements:baeldung.Foo)
|
||||||
|
FooOrBuilder {
|
||||||
|
// Use Foo.newBuilder() to construct.
|
||||||
|
private Foo(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
|
||||||
|
super(builder);
|
||||||
|
this.unknownFields = builder.getUnknownFields();
|
||||||
|
}
|
||||||
|
private Foo(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
|
||||||
|
|
||||||
|
private static final Foo defaultInstance;
|
||||||
|
public static Foo getDefaultInstance() {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Foo getDefaultInstanceForType() {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final com.google.protobuf.UnknownFieldSet unknownFields;
|
||||||
|
@java.lang.Override
|
||||||
|
public final com.google.protobuf.UnknownFieldSet
|
||||||
|
getUnknownFields() {
|
||||||
|
return this.unknownFields;
|
||||||
|
}
|
||||||
|
private Foo(
|
||||||
|
com.google.protobuf.CodedInputStream input,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||||
|
initFields();
|
||||||
|
int mutable_bitField0_ = 0;
|
||||||
|
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
|
||||||
|
com.google.protobuf.UnknownFieldSet.newBuilder();
|
||||||
|
try {
|
||||||
|
boolean done = false;
|
||||||
|
while (!done) {
|
||||||
|
int tag = input.readTag();
|
||||||
|
switch (tag) {
|
||||||
|
case 0:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
if (!parseUnknownField(input, unknownFields,
|
||||||
|
extensionRegistry, tag)) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8: {
|
||||||
|
bitField0_ |= 0x00000001;
|
||||||
|
id_ = input.readInt64();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 18: {
|
||||||
|
com.google.protobuf.ByteString bs = input.readBytes();
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
name_ = bs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||||
|
throw e.setUnfinishedMessage(this);
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
throw new com.google.protobuf.InvalidProtocolBufferException(
|
||||||
|
e.getMessage()).setUnfinishedMessage(this);
|
||||||
|
} finally {
|
||||||
|
this.unknownFields = unknownFields.build();
|
||||||
|
makeExtensionsImmutable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static final com.google.protobuf.Descriptors.Descriptor
|
||||||
|
getDescriptor() {
|
||||||
|
return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||||
|
internalGetFieldAccessorTable() {
|
||||||
|
return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_fieldAccessorTable
|
||||||
|
.ensureFieldAccessorsInitialized(
|
||||||
|
org.baeldung.web.dto.FooProtos.Foo.class, org.baeldung.web.dto.FooProtos.Foo.Builder.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static com.google.protobuf.Parser<Foo> PARSER =
|
||||||
|
new com.google.protobuf.AbstractParser<Foo>() {
|
||||||
|
public Foo parsePartialFrom(
|
||||||
|
com.google.protobuf.CodedInputStream input,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||||
|
return new Foo(input, extensionRegistry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
public com.google.protobuf.Parser<Foo> getParserForType() {
|
||||||
|
return PARSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int bitField0_;
|
||||||
|
public static final int ID_FIELD_NUMBER = 1;
|
||||||
|
private long id_;
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
public boolean hasId() {
|
||||||
|
return ((bitField0_ & 0x00000001) == 0x00000001);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
public long getId() {
|
||||||
|
return id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int NAME_FIELD_NUMBER = 2;
|
||||||
|
private java.lang.Object name_;
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public boolean hasName() {
|
||||||
|
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public java.lang.String getName() {
|
||||||
|
java.lang.Object ref = name_;
|
||||||
|
if (ref instanceof java.lang.String) {
|
||||||
|
return (java.lang.String) ref;
|
||||||
|
} else {
|
||||||
|
com.google.protobuf.ByteString bs =
|
||||||
|
(com.google.protobuf.ByteString) ref;
|
||||||
|
java.lang.String s = bs.toStringUtf8();
|
||||||
|
if (bs.isValidUtf8()) {
|
||||||
|
name_ = s;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getNameBytes() {
|
||||||
|
java.lang.Object ref = name_;
|
||||||
|
if (ref instanceof java.lang.String) {
|
||||||
|
com.google.protobuf.ByteString b =
|
||||||
|
com.google.protobuf.ByteString.copyFromUtf8(
|
||||||
|
(java.lang.String) ref);
|
||||||
|
name_ = b;
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return (com.google.protobuf.ByteString) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFields() {
|
||||||
|
id_ = 0L;
|
||||||
|
name_ = "";
|
||||||
|
}
|
||||||
|
private byte memoizedIsInitialized = -1;
|
||||||
|
public final boolean isInitialized() {
|
||||||
|
byte isInitialized = memoizedIsInitialized;
|
||||||
|
if (isInitialized == 1) return true;
|
||||||
|
if (isInitialized == 0) return false;
|
||||||
|
|
||||||
|
if (!hasId()) {
|
||||||
|
memoizedIsInitialized = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!hasName()) {
|
||||||
|
memoizedIsInitialized = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memoizedIsInitialized = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||||
|
throws java.io.IOException {
|
||||||
|
getSerializedSize();
|
||||||
|
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
|
output.writeInt64(1, id_);
|
||||||
|
}
|
||||||
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
|
output.writeBytes(2, getNameBytes());
|
||||||
|
}
|
||||||
|
getUnknownFields().writeTo(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int memoizedSerializedSize = -1;
|
||||||
|
public int getSerializedSize() {
|
||||||
|
int size = memoizedSerializedSize;
|
||||||
|
if (size != -1) return size;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
|
size += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeInt64Size(1, id_);
|
||||||
|
}
|
||||||
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
|
size += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeBytesSize(2, getNameBytes());
|
||||||
|
}
|
||||||
|
size += getUnknownFields().getSerializedSize();
|
||||||
|
memoizedSerializedSize = size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 0L;
|
||||||
|
@java.lang.Override
|
||||||
|
protected java.lang.Object writeReplace()
|
||||||
|
throws java.io.ObjectStreamException {
|
||||||
|
return super.writeReplace();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(
|
||||||
|
com.google.protobuf.ByteString data)
|
||||||
|
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||||
|
return PARSER.parseFrom(data);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(
|
||||||
|
com.google.protobuf.ByteString data,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||||
|
return PARSER.parseFrom(data, extensionRegistry);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(byte[] data)
|
||||||
|
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||||
|
return PARSER.parseFrom(data);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(
|
||||||
|
byte[] data,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||||
|
return PARSER.parseFrom(data, extensionRegistry);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(java.io.InputStream input)
|
||||||
|
throws java.io.IOException {
|
||||||
|
return PARSER.parseFrom(input);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(
|
||||||
|
java.io.InputStream input,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws java.io.IOException {
|
||||||
|
return PARSER.parseFrom(input, extensionRegistry);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseDelimitedFrom(java.io.InputStream input)
|
||||||
|
throws java.io.IOException {
|
||||||
|
return PARSER.parseDelimitedFrom(input);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseDelimitedFrom(
|
||||||
|
java.io.InputStream input,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws java.io.IOException {
|
||||||
|
return PARSER.parseDelimitedFrom(input, extensionRegistry);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(
|
||||||
|
com.google.protobuf.CodedInputStream input)
|
||||||
|
throws java.io.IOException {
|
||||||
|
return PARSER.parseFrom(input);
|
||||||
|
}
|
||||||
|
public static org.baeldung.web.dto.FooProtos.Foo parseFrom(
|
||||||
|
com.google.protobuf.CodedInputStream input,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws java.io.IOException {
|
||||||
|
return PARSER.parseFrom(input, extensionRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder newBuilder() { return Builder.create(); }
|
||||||
|
public Builder newBuilderForType() { return newBuilder(); }
|
||||||
|
public static Builder newBuilder(org.baeldung.web.dto.FooProtos.Foo prototype) {
|
||||||
|
return newBuilder().mergeFrom(prototype);
|
||||||
|
}
|
||||||
|
public Builder toBuilder() { return newBuilder(this); }
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
protected Builder newBuilderForType(
|
||||||
|
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
|
||||||
|
Builder builder = new Builder(parent);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Protobuf type {@code baeldung.Foo}
|
||||||
|
*/
|
||||||
|
public static final class Builder extends
|
||||||
|
com.google.protobuf.GeneratedMessage.Builder<Builder> implements
|
||||||
|
// @@protoc_insertion_point(builder_implements:baeldung.Foo)
|
||||||
|
org.baeldung.web.dto.FooProtos.FooOrBuilder {
|
||||||
|
public static final com.google.protobuf.Descriptors.Descriptor
|
||||||
|
getDescriptor() {
|
||||||
|
return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||||
|
internalGetFieldAccessorTable() {
|
||||||
|
return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_fieldAccessorTable
|
||||||
|
.ensureFieldAccessorsInitialized(
|
||||||
|
org.baeldung.web.dto.FooProtos.Foo.class, org.baeldung.web.dto.FooProtos.Foo.Builder.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct using org.baeldung.web.dto.FooProtos.Foo.newBuilder()
|
||||||
|
private Builder() {
|
||||||
|
maybeForceBuilderInitialization();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Builder(
|
||||||
|
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
|
||||||
|
super(parent);
|
||||||
|
maybeForceBuilderInitialization();
|
||||||
|
}
|
||||||
|
private void maybeForceBuilderInitialization() {
|
||||||
|
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static Builder create() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder clear() {
|
||||||
|
super.clear();
|
||||||
|
id_ = 0L;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000001);
|
||||||
|
name_ = "";
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder clone() {
|
||||||
|
return create().mergeFrom(buildPartial());
|
||||||
|
}
|
||||||
|
|
||||||
|
public com.google.protobuf.Descriptors.Descriptor
|
||||||
|
getDescriptorForType() {
|
||||||
|
return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.baeldung.web.dto.FooProtos.Foo getDefaultInstanceForType() {
|
||||||
|
return org.baeldung.web.dto.FooProtos.Foo.getDefaultInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.baeldung.web.dto.FooProtos.Foo build() {
|
||||||
|
org.baeldung.web.dto.FooProtos.Foo result = buildPartial();
|
||||||
|
if (!result.isInitialized()) {
|
||||||
|
throw newUninitializedMessageException(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public org.baeldung.web.dto.FooProtos.Foo buildPartial() {
|
||||||
|
org.baeldung.web.dto.FooProtos.Foo result = new org.baeldung.web.dto.FooProtos.Foo(this);
|
||||||
|
int from_bitField0_ = bitField0_;
|
||||||
|
int to_bitField0_ = 0;
|
||||||
|
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
|
to_bitField0_ |= 0x00000001;
|
||||||
|
}
|
||||||
|
result.id_ = id_;
|
||||||
|
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
|
to_bitField0_ |= 0x00000002;
|
||||||
|
}
|
||||||
|
result.name_ = name_;
|
||||||
|
result.bitField0_ = to_bitField0_;
|
||||||
|
onBuilt();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mergeFrom(com.google.protobuf.Message other) {
|
||||||
|
if (other instanceof org.baeldung.web.dto.FooProtos.Foo) {
|
||||||
|
return mergeFrom((org.baeldung.web.dto.FooProtos.Foo)other);
|
||||||
|
} else {
|
||||||
|
super.mergeFrom(other);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mergeFrom(org.baeldung.web.dto.FooProtos.Foo other) {
|
||||||
|
if (other == org.baeldung.web.dto.FooProtos.Foo.getDefaultInstance()) return this;
|
||||||
|
if (other.hasId()) {
|
||||||
|
setId(other.getId());
|
||||||
|
}
|
||||||
|
if (other.hasName()) {
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
name_ = other.name_;
|
||||||
|
onChanged();
|
||||||
|
}
|
||||||
|
this.mergeUnknownFields(other.getUnknownFields());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isInitialized() {
|
||||||
|
if (!hasId()) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!hasName()) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder mergeFrom(
|
||||||
|
com.google.protobuf.CodedInputStream input,
|
||||||
|
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||||
|
throws java.io.IOException {
|
||||||
|
org.baeldung.web.dto.FooProtos.Foo parsedMessage = null;
|
||||||
|
try {
|
||||||
|
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
|
||||||
|
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||||
|
parsedMessage = (org.baeldung.web.dto.FooProtos.Foo) e.getUnfinishedMessage();
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
if (parsedMessage != null) {
|
||||||
|
mergeFrom(parsedMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
private int bitField0_;
|
||||||
|
|
||||||
|
private long id_ ;
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
public boolean hasId() {
|
||||||
|
return ((bitField0_ & 0x00000001) == 0x00000001);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
public long getId() {
|
||||||
|
return id_;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
public Builder setId(long value) {
|
||||||
|
bitField0_ |= 0x00000001;
|
||||||
|
id_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required int64 id = 1;</code>
|
||||||
|
*/
|
||||||
|
public Builder clearId() {
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000001);
|
||||||
|
id_ = 0L;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private java.lang.Object name_ = "";
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public boolean hasName() {
|
||||||
|
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public java.lang.String getName() {
|
||||||
|
java.lang.Object ref = name_;
|
||||||
|
if (!(ref instanceof java.lang.String)) {
|
||||||
|
com.google.protobuf.ByteString bs =
|
||||||
|
(com.google.protobuf.ByteString) ref;
|
||||||
|
java.lang.String s = bs.toStringUtf8();
|
||||||
|
if (bs.isValidUtf8()) {
|
||||||
|
name_ = s;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
return (java.lang.String) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getNameBytes() {
|
||||||
|
java.lang.Object ref = name_;
|
||||||
|
if (ref instanceof String) {
|
||||||
|
com.google.protobuf.ByteString b =
|
||||||
|
com.google.protobuf.ByteString.copyFromUtf8(
|
||||||
|
(java.lang.String) ref);
|
||||||
|
name_ = b;
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return (com.google.protobuf.ByteString) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public Builder setName(
|
||||||
|
java.lang.String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
name_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public Builder clearName() {
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
|
name_ = getDefaultInstance().getName();
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>required string name = 2;</code>
|
||||||
|
*/
|
||||||
|
public Builder setNameBytes(
|
||||||
|
com.google.protobuf.ByteString value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
name_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(builder_scope:baeldung.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
defaultInstance = new Foo(true);
|
||||||
|
defaultInstance.initFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(class_scope:baeldung.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final com.google.protobuf.Descriptors.Descriptor
|
||||||
|
internal_static_baeldung_Foo_descriptor;
|
||||||
|
private static
|
||||||
|
com.google.protobuf.GeneratedMessage.FieldAccessorTable
|
||||||
|
internal_static_baeldung_Foo_fieldAccessorTable;
|
||||||
|
|
||||||
|
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
getDescriptor() {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
private static com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
descriptor;
|
||||||
|
static {
|
||||||
|
java.lang.String[] descriptorData = {
|
||||||
|
"\n\017FooProtos.proto\022\010baeldung\"\037\n\003Foo\022\n\n\002id" +
|
||||||
|
"\030\001 \002(\003\022\014\n\004name\030\002 \002(\tB!\n\024org.baeldung.web" +
|
||||||
|
".dtoB\tFooProtos"
|
||||||
|
};
|
||||||
|
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||||
|
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||||
|
public com.google.protobuf.ExtensionRegistry assignDescriptors(
|
||||||
|
com.google.protobuf.Descriptors.FileDescriptor root) {
|
||||||
|
descriptor = root;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
.internalBuildGeneratedFileFrom(descriptorData,
|
||||||
|
new com.google.protobuf.Descriptors.FileDescriptor[] {
|
||||||
|
}, assigner);
|
||||||
|
internal_static_baeldung_Foo_descriptor =
|
||||||
|
getDescriptor().getMessageTypes().get(0);
|
||||||
|
internal_static_baeldung_Foo_fieldAccessorTable = new
|
||||||
|
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||||
|
internal_static_baeldung_Foo_descriptor,
|
||||||
|
new java.lang.String[] { "Id", "Name", });
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(outer_class_scope)
|
||||||
|
}
|
36
spring-rest/src/main/java/org/baeldung/web/dto/Item.java
Normal file
36
spring-rest/src/main/java/org/baeldung/web/dto/Item.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package org.baeldung.web.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
|
||||||
|
public class Item {
|
||||||
|
@JsonView(Views.Public.class)
|
||||||
|
public int id;
|
||||||
|
|
||||||
|
@JsonView(Views.Public.class)
|
||||||
|
public String itemName;
|
||||||
|
|
||||||
|
@JsonView(Views.Internal.class)
|
||||||
|
public String ownerName;
|
||||||
|
|
||||||
|
public Item() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item(final int id, final String itemName, final String ownerName) {
|
||||||
|
this.id = id;
|
||||||
|
this.itemName = itemName;
|
||||||
|
this.ownerName = ownerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getItemName() {
|
||||||
|
return itemName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOwnerName() {
|
||||||
|
return ownerName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.baeldung.web.dto;
|
||||||
|
|
||||||
|
public class ItemManager {
|
||||||
|
|
||||||
|
public static Item getById(final int id) {
|
||||||
|
final Item item = new Item(2, "book", "John");
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.baeldung.web.dto;
|
||||||
|
|
||||||
|
public class Views {
|
||||||
|
public static class Public {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Internal extends Public {
|
||||||
|
}
|
||||||
|
}
|
20
spring-rest/src/main/resources/logback.xml
Normal file
20
spring-rest/src/main/resources/logback.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<logger name="org.springframework" level="WARN" />
|
||||||
|
<logger name="org.springframework.transaction" level="WARN" />
|
||||||
|
|
||||||
|
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
||||||
|
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
33
spring-rest/src/main/webapp/WEB-INF/api-servlet.xml
Normal file
33
spring-rest/src/main/webapp/WEB-INF/api-servlet.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||||
|
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"
|
||||||
|
>
|
||||||
|
|
||||||
|
<context:component-scan base-package="org.baeldung.web" />
|
||||||
|
|
||||||
|
<mvc:annotation-driven />
|
||||||
|
|
||||||
|
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
|
||||||
|
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
|
||||||
|
<property name="location">
|
||||||
|
<value>/WEB-INF/spring-views.xml</value>
|
||||||
|
</property>
|
||||||
|
<property name="order" value="0" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
|
||||||
|
<!-- max upload size in bytes -->
|
||||||
|
<property name="maxUploadSize" value="20971520" /> <!-- 20MB -->
|
||||||
|
|
||||||
|
<!-- max size of file in memory (in bytes) -->
|
||||||
|
<property name="maxInMemorySize" value="1048576" /> <!-- 1MB -->
|
||||||
|
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
</beans>
|
||||||
|
|
||||||
|
|
44
spring-rest/src/main/webapp/WEB-INF/company.html
Normal file
44
spring-rest/src/main/webapp/WEB-INF/company.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="ISO-8859-1">
|
||||||
|
<title>Company Data</title>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.1.0.js"
|
||||||
|
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('#REST-button').click(function() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'http://localhost:8080/spring-rest/companyRest?callback=getCompanyData',
|
||||||
|
data: {
|
||||||
|
format: 'json'
|
||||||
|
},
|
||||||
|
type: 'GET',
|
||||||
|
jsonpCallback:'getCompanyData',
|
||||||
|
dataType: 'jsonp',
|
||||||
|
error: function() {
|
||||||
|
$('#infoREST').html('<p>An error has occurred</p>');
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
console.log("sucess");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function getCompanyData(data) {
|
||||||
|
document.write("<b>ID:</b> "+data.id+"<br/>");
|
||||||
|
document.write("<b>NAME:</b> "+data.name+"<br/>");
|
||||||
|
document.write("<br/>");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Using REST URL-->
|
||||||
|
<button id="REST-button">Test REST JSON-P!</button>
|
||||||
|
<div id="infoREST"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
10
spring-rest/src/main/webapp/WEB-INF/spring-views.xml
Normal file
10
spring-rest/src/main/webapp/WEB-INF/spring-views.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
|
||||||
|
>
|
||||||
|
|
||||||
|
<bean id="RedirectedUrl" class="org.springframework.web.servlet.view.RedirectView">
|
||||||
|
<property name="url" value="redirectedUrl" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
41
spring-rest/src/main/webapp/WEB-INF/web.xml
Normal file
41
spring-rest/src/main/webapp/WEB-INF/web.xml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||||
|
xsi:schemaLocation="
|
||||||
|
http://java.sun.com/xml/ns/javaee
|
||||||
|
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"
|
||||||
|
>
|
||||||
|
|
||||||
|
<display-name>Spring MVC Application</display-name>
|
||||||
|
|
||||||
|
<!-- Spring root -->
|
||||||
|
<context-param>
|
||||||
|
<param-name>contextClass</param-name>
|
||||||
|
<param-value>
|
||||||
|
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||||
|
</param-value>
|
||||||
|
</context-param>
|
||||||
|
<context-param>
|
||||||
|
<param-name>contextConfigLocation</param-name>
|
||||||
|
<param-value>org.baeldung.config</param-value>
|
||||||
|
</context-param>
|
||||||
|
|
||||||
|
<listener>
|
||||||
|
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||||
|
</listener>
|
||||||
|
|
||||||
|
<!-- Spring child -->
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>api</servlet-name>
|
||||||
|
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>api</servlet-name>
|
||||||
|
<url-pattern>/</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<welcome-file-list>
|
||||||
|
<welcome-file/>
|
||||||
|
</welcome-file-list>
|
||||||
|
|
||||||
|
</web-app>
|
@ -0,0 +1,67 @@
|
|||||||
|
package org.baeldung.web.controller.redirect;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.flash;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
|
||||||
|
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration("file:src/main/webapp/WEB-INF/api-servlet.xml")
|
||||||
|
@WebAppConfiguration
|
||||||
|
public class RedirectControllerTest {
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected WebApplicationContext wac;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
mockMvc = webAppContextSetup(wac).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRedirectOnUrlWithUsingXMLConfig_thenStatusRedirectionAndRedirectedOnUrl() throws Exception {
|
||||||
|
mockMvc.perform(get("/redirectWithXMLConfig")).andExpect(status().is3xxRedirection()).andExpect(view().name("RedirectedUrl")).andExpect(model().attribute("attribute", is("redirectWithXMLConfig")))
|
||||||
|
.andExpect(redirectedUrl("redirectedUrl?attribute=redirectWithXMLConfig"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRedirectOnUrlWithUsingRedirectPrefix_thenStatusRedirectionAndRedirectedOnUrl() throws Exception {
|
||||||
|
mockMvc.perform(get("/redirectWithRedirectPrefix")).andExpect(status().is3xxRedirection()).andExpect(view().name("redirect:/redirectedUrl")).andExpect(model().attribute("attribute", is("redirectWithRedirectPrefix")))
|
||||||
|
.andExpect(redirectedUrl("/redirectedUrl?attribute=redirectWithRedirectPrefix"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRedirectOnUrlWithUsingRedirectAttributes_thenStatusRedirectionAndRedirectedOnUrlAndAddedAttributeToFlashScope() throws Exception {
|
||||||
|
mockMvc.perform(get("/redirectWithRedirectAttributes")).andExpect(status().is3xxRedirection()).andExpect(flash().attribute("flashAttribute", is("redirectWithRedirectAttributes")))
|
||||||
|
.andExpect(model().attribute("attribute", is("redirectWithRedirectAttributes"))).andExpect(model().attribute("flashAttribute", is(nullValue()))).andExpect(redirectedUrl("redirectedUrl?attribute=redirectWithRedirectAttributes"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRedirectOnUrlWithUsingRedirectView_thenStatusRedirectionAndRedirectedOnUrlAndAddedAttributeToFlashScope() throws Exception {
|
||||||
|
mockMvc.perform(get("/redirectWithRedirectView")).andExpect(status().is3xxRedirection()).andExpect(model().attribute("attribute", is("redirectWithRedirectView"))).andExpect(redirectedUrl("redirectedUrl?attribute=redirectWithRedirectView"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRedirectOnUrlWithUsingForwardPrefix_thenStatusOkAndForwardedOnUrl() throws Exception {
|
||||||
|
mockMvc.perform(get("/forwardWithForwardPrefix")).andExpect(status().isOk()).andExpect(view().name("forward:/redirectedUrl")).andExpect(model().attribute("attribute", is("redirectWithForwardPrefix"))).andExpect(forwardedUrl("/redirectedUrl"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.baeldung.web.controller.status;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import org.baeldung.config.WebConfig;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(classes = WebConfig.class)
|
||||||
|
@WebAppConfiguration
|
||||||
|
public class ExampleControllerTest {
|
||||||
|
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebApplicationContext webApplicationContext;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetRequestSentToController_thenReturnsStatusNotAcceptable() throws Exception {
|
||||||
|
mockMvc.perform(get("/controller"))
|
||||||
|
.andExpect(status().isNotAcceptable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetRequestSentToException_thenReturnsStatusForbidden() throws Exception {
|
||||||
|
mockMvc.perform(get("/exception"))
|
||||||
|
.andExpect(status().isForbidden());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
package org.baeldung.web.test;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.baeldung.config.converter.KryoHttpMessageConverter;
|
||||||
|
import org.baeldung.web.dto.Foo;
|
||||||
|
import org.baeldung.web.dto.FooProtos;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
|
||||||
|
import org.springframework.oxm.xstream.XStreamMarshaller;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration Test class. Tests methods hits the server's rest services.
|
||||||
|
*/
|
||||||
|
public class SpringHttpMessageConvertersIntegrationTestsCase {
|
||||||
|
|
||||||
|
private static String BASE_URI = "http://localhost:8080/spring-rest/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Without specifying Accept Header, uses the default response from the
|
||||||
|
* server (in this case json)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void whenRetrievingAFoo_thenCorrect() {
|
||||||
|
final String URI = BASE_URI + "foos/{id}";
|
||||||
|
|
||||||
|
final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
final Foo resource = restTemplate.getForObject(URI, Foo.class, "1");
|
||||||
|
|
||||||
|
assertThat(resource, notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenConsumingXml_whenReadingTheFoo_thenCorrect() {
|
||||||
|
final String URI = BASE_URI + "foos/{id}";
|
||||||
|
|
||||||
|
final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setMessageConverters(getMessageConverters());
|
||||||
|
|
||||||
|
final HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
|
||||||
|
final HttpEntity<String> entity = new HttpEntity<String>(headers);
|
||||||
|
|
||||||
|
final ResponseEntity<Foo> response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1");
|
||||||
|
final Foo resource = response.getBody();
|
||||||
|
|
||||||
|
assertThat(resource, notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenConsumingJson_whenReadingTheFoo_thenCorrect() {
|
||||||
|
final String URI = BASE_URI + "foos/{id}";
|
||||||
|
|
||||||
|
final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setMessageConverters(getMessageConverters());
|
||||||
|
|
||||||
|
final HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||||
|
final HttpEntity<String> entity = new HttpEntity<String>(headers);
|
||||||
|
|
||||||
|
final ResponseEntity<Foo> response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1");
|
||||||
|
final Foo resource = response.getBody();
|
||||||
|
|
||||||
|
assertThat(resource, notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenConsumingXml_whenWritingTheFoo_thenCorrect() {
|
||||||
|
final String URI = BASE_URI + "foos/{id}";
|
||||||
|
final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setMessageConverters(getMessageConverters());
|
||||||
|
|
||||||
|
final Foo resource = new Foo(4, "jason");
|
||||||
|
final HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
|
||||||
|
headers.setContentType((MediaType.APPLICATION_XML));
|
||||||
|
final HttpEntity<Foo> entity = new HttpEntity<Foo>(resource, headers);
|
||||||
|
|
||||||
|
final ResponseEntity<Foo> response = restTemplate.exchange(URI, HttpMethod.PUT, entity, Foo.class, resource.getId());
|
||||||
|
final Foo fooResponse = response.getBody();
|
||||||
|
|
||||||
|
Assert.assertEquals(resource.getId(), fooResponse.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenConsumingProtobuf_whenReadingTheFoo_thenCorrect() {
|
||||||
|
final String URI = BASE_URI + "foos/{id}";
|
||||||
|
|
||||||
|
final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setMessageConverters(Arrays.asList(new ProtobufHttpMessageConverter()));
|
||||||
|
final HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Arrays.asList(ProtobufHttpMessageConverter.PROTOBUF));
|
||||||
|
final HttpEntity<String> entity = new HttpEntity<String>(headers);
|
||||||
|
|
||||||
|
final ResponseEntity<FooProtos.Foo> response = restTemplate.exchange(URI, HttpMethod.GET, entity, FooProtos.Foo.class, "1");
|
||||||
|
final FooProtos.Foo resource = response.getBody();
|
||||||
|
|
||||||
|
assertThat(resource, notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenConsumingKryo_whenReadingTheFoo_thenCorrect() {
|
||||||
|
final String URI = BASE_URI + "foos/{id}";
|
||||||
|
|
||||||
|
final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
restTemplate.setMessageConverters(Arrays.asList(new KryoHttpMessageConverter()));
|
||||||
|
final HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setAccept(Arrays.asList(KryoHttpMessageConverter.KRYO));
|
||||||
|
final HttpEntity<String> entity = new HttpEntity<String>(headers);
|
||||||
|
|
||||||
|
final ResponseEntity<Foo> response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1");
|
||||||
|
final Foo resource = response.getBody();
|
||||||
|
|
||||||
|
assertThat(resource, notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTIL
|
||||||
|
|
||||||
|
private List<HttpMessageConverter<?>> getMessageConverters() {
|
||||||
|
final List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||||
|
|
||||||
|
final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
|
||||||
|
final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();
|
||||||
|
xmlConverter.setMarshaller(xstreamMarshaller);
|
||||||
|
xmlConverter.setUnmarshaller(xstreamMarshaller);
|
||||||
|
|
||||||
|
converters.add(xmlConverter);
|
||||||
|
converters.add(new MappingJackson2HttpMessageConverter());
|
||||||
|
|
||||||
|
return converters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
spring-rest/src/test/resources/.gitignore
vendored
Normal file
13
spring-rest/src/test/resources/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
*.class
|
||||||
|
|
||||||
|
#folders#
|
||||||
|
/target
|
||||||
|
/neoDb*
|
||||||
|
/data
|
||||||
|
/src/main/webapp/WEB-INF/classes
|
||||||
|
*/META-INF/*
|
||||||
|
|
||||||
|
# Packaged files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
Loading…
x
Reference in New Issue
Block a user