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>
|
||||
<artifactId>hystrix</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- General -->
|
||||
@ -32,12 +38,35 @@
|
||||
|
||||
<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>
|
||||
<groupId>com.netflix.hystrix</groupId>
|
||||
<artifactId>hystrix-core</artifactId>
|
||||
<version>${hystrix-core.version}</version>
|
||||
</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>
|
||||
<groupId>com.netflix.rxjava</groupId>
|
||||
<artifactId>rxjava-core</artifactId>
|
||||
@ -62,6 +91,10 @@
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<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;
|
||||
|
||||
|
||||
class RemoteServiceTestSimulator {
|
||||
public class RemoteServiceTestSimulator {
|
||||
|
||||
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.rules.ExpectedException;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class HystrixTimeoutTest {
|
||||
|
||||
private static HystrixCommand.Setter config;
|
||||
private static HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter();
|
||||
private HystrixCommand.Setter config;
|
||||
private HystrixCommandProperties.Setter commandProperties ;
|
||||
|
||||
|
||||
@Rule
|
||||
@ -23,6 +25,7 @@ public class HystrixTimeoutTest {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
commandProperties = HystrixCommandProperties.Setter();
|
||||
config = HystrixCommand
|
||||
.Setter
|
||||
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroup1"));
|
||||
@ -34,29 +37,86 @@ public class HystrixTimeoutTest {
|
||||
}
|
||||
|
||||
@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"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimeoutEqualTo10000_andDefaultSettings_thenExpectHystrixRuntimeException() throws InterruptedException {
|
||||
public void givenServiceTimeoutEqualTo10000_andDefaultSettings_thenExpectHRE() throws InterruptedException {
|
||||
exception.expect(HystrixRuntimeException.class);
|
||||
new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(10_000)).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimeoutEqualTo5000_andExecutionTimeoutEqualTo10000_thenReturnSuccess() throws InterruptedException {
|
||||
public void givenServiceTimeoutEqualTo5000_andExecutionTimeoutEqualTo10000_thenReturnSuccess()
|
||||
throws InterruptedException {
|
||||
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
|
||||
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
|
||||
public void givenTimeoutEqualTo15000_andExecutionTimeoutEqualTo10000_thenExpectHystrixRuntimeException() throws InterruptedException {
|
||||
public void givenServiceTimeoutEqualTo15000_andExecutionTimeoutEqualTo5000_thenExpectHRE()
|
||||
throws InterruptedException {
|
||||
exception.expect(HystrixRuntimeException.class);
|
||||
commandProperties.withExecutionTimeoutInMilliseconds(10_000);
|
||||
commandProperties.withExecutionTimeoutInMilliseconds(5_000);
|
||||
config.andCommandPropertiesDefaults(commandProperties);
|
||||
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>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-ehcache</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xml-apis</groupId>
|
||||
<artifactId>xml-apis</artifactId>
|
||||
@ -50,6 +55,11 @@
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>${spring-data-jpa.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- validation -->
|
||||
|
||||
@ -186,6 +196,7 @@
|
||||
<hibernate.version>4.3.11.Final</hibernate.version>
|
||||
<mysql-connector-java.version>5.1.38</mysql-connector-java.version>
|
||||
<spring-data-jpa.version>1.8.2.RELEASE</spring-data-jpa.version>
|
||||
<h2.version>1.4.192</h2.version>
|
||||
|
||||
<!-- logging -->
|
||||
<org.slf4j.version>1.7.13</org.slf4j.version>
|
||||
|
@ -78,6 +78,8 @@ public class PersistenceJPAConfig {
|
||||
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.globally_quoted_identifiers", "true");
|
||||
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;
|
||||
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
import javax.persistence.*;
|
||||
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
|
||||
@Cacheable
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
public class Foo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -21,6 +21,8 @@
|
||||
<props>
|
||||
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</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>
|
||||
</property>
|
||||
</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.show_sql=false
|
||||
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.show_sql=false
|
||||
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"?>
|
||||
<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" >
|
||||
<class>org.baeldung.persistence.model.Foo</class>
|
||||
<class>org.baeldung.persistence.model.Bar</class>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||
<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.ddl-generation" value="drop-and-create-tables"/>
|
||||
<property name="javax.persistence.logging.level" value="INFO"/>
|
||||
<property name = "hibernate.show_sql" value = "true" />
|
||||
</properties>
|
||||
|
||||
</persistence-unit>
|
||||
<persistence-unit name="punit" >
|
||||
<class>org.baeldung.persistence.model.Foo</class>
|
||||
<class>org.baeldung.persistence.model.Bar</class>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||
<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.ddl-generation" value="drop-and-create-tables"/>
|
||||
<property name="javax.persistence.logging.level" value="INFO"/>
|
||||
<property name = "hibernate.show_sql" value = "true" />
|
||||
<property name = "hibernate.cache.use_second_level_cache" value = "false" />
|
||||
<property name = "hibernate.cache.use_query_cache" value = "false" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</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