Merge remote-tracking branch 'origin/master' into bael-965-collection-util
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
Example for the Article on Camel API with SpringBoot
|
||||
|
||||
to start up, run:
|
||||
mvn spring-boot:run
|
||||
|
||||
them, do a POST http request to:
|
||||
http://localhost:8080/camel/api/bean
|
||||
|
||||
with the HEADER: Content-Type: application/json,
|
||||
|
||||
and a BODY Payload like {"id": 1,"name": "World"}
|
||||
|
||||
and we will get a return code of 201 and the response: Hello, World - if the transform() method from Application class is uncommented and the process() method is commented
|
||||
|
||||
or return code of 201 and the response: {"id": 10,"name": "Hello, World"} - if the transform() method from Application class is commented and the process() method is uncommented
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>spring-boot-camel</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<name>Spring-Boot - Camel API</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||
<camel.version>2.19.1</camel.version>
|
||||
<spring-boot-starter.version>1.5.4.RELEASE</spring-boot-starter.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-servlet-starter</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-jackson-starter</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-swagger-java-starter</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-spring-boot-starter</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>spring-boot:run</defaultGoal>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot-starter.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.baeldung.camel;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.apache.camel.CamelContext;
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.Processor;
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
|
||||
import org.apache.camel.impl.DefaultCamelContext;
|
||||
import org.apache.camel.model.rest.RestBindingMode;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages="com.baeldung.camel")
|
||||
public class Application extends SpringBootServletInitializer {
|
||||
|
||||
@Value("${server.port}")
|
||||
String serverPort;
|
||||
|
||||
@Value("${baeldung.api.path}")
|
||||
String contextPath;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
ServletRegistrationBean servletRegistrationBean() {
|
||||
ServletRegistrationBean servlet = new ServletRegistrationBean(new CamelHttpTransportServlet(), contextPath+"/*");
|
||||
servlet.setName("CamelServlet");
|
||||
return servlet;
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
class RestApi extends RouteBuilder {
|
||||
|
||||
@Override
|
||||
public void configure() {
|
||||
|
||||
CamelContext context = new DefaultCamelContext();
|
||||
|
||||
|
||||
// http://localhost:8080/camel/api-doc
|
||||
restConfiguration().contextPath(contextPath) //
|
||||
.port(serverPort)
|
||||
.enableCORS(true)
|
||||
.apiContextPath("/api-doc")
|
||||
.apiProperty("api.title", "Test REST API")
|
||||
.apiProperty("api.version", "v1")
|
||||
.apiProperty("cors", "true") // cross-site
|
||||
.apiContextRouteId("doc-api")
|
||||
.component("servlet")
|
||||
.bindingMode(RestBindingMode.json)
|
||||
.dataFormatProperty("prettyPrint", "true");
|
||||
/**
|
||||
The Rest DSL supports automatic binding json/xml contents to/from POJOs using Camels Data Format.
|
||||
By default the binding mode is off, meaning there is no automatic binding happening for incoming and outgoing messages.
|
||||
You may want to use binding if you develop POJOs that maps to your REST services request and response types.
|
||||
This allows you, as a developer, to work with the POJOs in Java code.
|
||||
*/
|
||||
|
||||
rest("/api/").description("Teste REST Service")
|
||||
.id("api-route")
|
||||
.post("/bean")
|
||||
.produces(MediaType.APPLICATION_JSON)
|
||||
.consumes(MediaType.APPLICATION_JSON)
|
||||
// .get("/hello/{place}")
|
||||
.bindingMode(RestBindingMode.auto)
|
||||
.type(MyBean.class)
|
||||
.enableCORS(true)
|
||||
// .outType(OutBean.class)
|
||||
|
||||
.to("direct:remoteService");
|
||||
|
||||
|
||||
from("direct:remoteService")
|
||||
.routeId("direct-route")
|
||||
.tracing()
|
||||
.log(">>> ${body.id}")
|
||||
.log(">>> ${body.name}")
|
||||
// .transform().simple("blue ${in.body.name}")
|
||||
.process(new Processor() {
|
||||
@Override
|
||||
public void process(Exchange exchange) throws Exception {
|
||||
MyBean bodyIn = (MyBean) exchange.getIn().getBody();
|
||||
|
||||
ExampleServices.example(bodyIn);
|
||||
|
||||
exchange.getIn().setBody(bodyIn);
|
||||
}
|
||||
})
|
||||
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(201));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.camel;
|
||||
|
||||
/**
|
||||
* a Mock class to show how some other layer
|
||||
* (a persistence layer, for instance)
|
||||
* could be used insida a Camel
|
||||
*
|
||||
*/
|
||||
public class ExampleServices {
|
||||
|
||||
public static void example(MyBean bodyIn) {
|
||||
bodyIn.setName( "Hello, " + bodyIn.getName() );
|
||||
bodyIn.setId(bodyIn.getId()*10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.camel;
|
||||
|
||||
public class MyBean {
|
||||
private Integer id;
|
||||
private String name;
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
logging.config=classpath:logback.xml
|
||||
|
||||
# the options from org.apache.camel.spring.boot.CamelConfigurationProperties can be configured here
|
||||
camel.springboot.name=MyCamel
|
||||
|
||||
# lets listen on all ports to ensure we can be invoked from the pod IP
|
||||
server.address=0.0.0.0
|
||||
management.address=0.0.0.0
|
||||
|
||||
# lets use a different management port in case you need to listen to HTTP requests on 8080
|
||||
management.port=8081
|
||||
|
||||
# disable all management enpoints except health
|
||||
endpoints.enabled = true
|
||||
endpoints.health.enabled = true
|
||||
@@ -0,0 +1,27 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
# for example purposes of Camel version 2.18 and below
|
||||
baeldung:
|
||||
api:
|
||||
path: '/camel'
|
||||
|
||||
camel:
|
||||
springboot:
|
||||
# The Camel context name
|
||||
name: ServicesRest
|
||||
|
||||
# Binding health checks to a different port
|
||||
management:
|
||||
port: 8081
|
||||
|
||||
# disable all management enpoints except health
|
||||
endpoints:
|
||||
enabled: false
|
||||
health:
|
||||
enabled: true
|
||||
|
||||
# The application configuration properties
|
||||
quickstart:
|
||||
generateOrderPeriod: 10s
|
||||
processOrderPeriod: 30s
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE xml>
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- encoders are assigned the type
|
||||
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -327,6 +327,22 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<configuration>
|
||||
<executable>java</executable>
|
||||
<mainClass>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</mainClass>
|
||||
<arguments>
|
||||
<argument>-Xmx300m</argument>
|
||||
<argument>-XX:+UseParallelGC</argument>
|
||||
<argument>-classpath</argument>
|
||||
<classpath/>
|
||||
<argument>com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.concurrent.semaphores;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
class CounterUsingMutex {
|
||||
|
||||
private final Semaphore mutex;
|
||||
private int count;
|
||||
|
||||
CounterUsingMutex() {
|
||||
mutex = new Semaphore(1);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void increase() throws InterruptedException {
|
||||
mutex.acquire();
|
||||
this.count = this.count + 1;
|
||||
Thread.sleep(1000);
|
||||
mutex.release();
|
||||
|
||||
}
|
||||
|
||||
int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
boolean hasQueuedThreads() {
|
||||
return mutex.hasQueuedThreads();
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.concurrent.semaphores;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang3.concurrent.TimedSemaphore;
|
||||
|
||||
class DelayQueueUsingTimedSemaphore {
|
||||
|
||||
private final TimedSemaphore semaphore;
|
||||
|
||||
DelayQueueUsingTimedSemaphore(long period, int slotLimit) {
|
||||
semaphore = new TimedSemaphore(period, TimeUnit.SECONDS, slotLimit);
|
||||
}
|
||||
|
||||
boolean tryAdd() {
|
||||
return semaphore.tryAcquire();
|
||||
}
|
||||
|
||||
int availableSlots() {
|
||||
return semaphore.getAvailablePermits();
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.concurrent.semaphores;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
class LoginQueueUsingSemaphore {
|
||||
|
||||
private final Semaphore semaphore;
|
||||
|
||||
LoginQueueUsingSemaphore(int slotLimit) {
|
||||
semaphore = new Semaphore(slotLimit);
|
||||
}
|
||||
|
||||
boolean tryLogin() {
|
||||
return semaphore.tryAcquire();
|
||||
}
|
||||
|
||||
void logout() {
|
||||
semaphore.release();
|
||||
}
|
||||
|
||||
int availableSlots() {
|
||||
return semaphore.availablePermits();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.outofmemoryerror;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class OutOfMemoryGCLimitExceed {
|
||||
public static void addRandomDataToMap() {
|
||||
Map<Integer, String> dataMap = new HashMap<>();
|
||||
Random r = new Random();
|
||||
while (true) {
|
||||
dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
OutOfMemoryGCLimitExceed.addRandomDataToMap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.typeerasure;
|
||||
|
||||
public class ArrayContentPrintUtil {
|
||||
|
||||
public static <E> void printArray(E[] array) {
|
||||
for (E element : array) {
|
||||
System.out.printf("%s ", element);
|
||||
}
|
||||
}
|
||||
|
||||
public static <E extends Comparable<E>> void printArray(E[] array) {
|
||||
for (E element : array) {
|
||||
System.out.printf("%s ", element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.typeerasure;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class BoundStack<E extends Comparable<E>> {
|
||||
|
||||
private E[] stackContent;
|
||||
private int total;
|
||||
|
||||
public BoundStack(int capacity) {
|
||||
this.stackContent = (E[]) new Object[capacity];
|
||||
}
|
||||
|
||||
public void push(E data) {
|
||||
if (total == stackContent.length) {
|
||||
resize(2 * stackContent.length);
|
||||
}
|
||||
stackContent[total++] = data;
|
||||
}
|
||||
|
||||
public E pop() {
|
||||
if (!isEmpty()) {
|
||||
E datum = stackContent[total];
|
||||
stackContent[total--] = null;
|
||||
return datum;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void resize(int capacity) {
|
||||
Arrays.copyOf(stackContent, capacity);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return total == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.typeerasure;
|
||||
|
||||
public class IntegerStack extends Stack<Integer> {
|
||||
|
||||
public IntegerStack(int capacity) {
|
||||
super(capacity);
|
||||
}
|
||||
|
||||
public void push(Integer value) {
|
||||
System.out.println("Pushing into my integerStack");
|
||||
super.push(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.typeerasure;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Stack<E> {
|
||||
|
||||
private E[] stackContent;
|
||||
private int total;
|
||||
|
||||
public Stack(int capacity) {
|
||||
this.stackContent = (E[]) new Object[capacity];
|
||||
}
|
||||
|
||||
public void push(E data) {
|
||||
System.out.println("In base stack push#");
|
||||
if (total == stackContent.length) {
|
||||
resize(2 * stackContent.length);
|
||||
}
|
||||
stackContent[total++] = data;
|
||||
}
|
||||
|
||||
public E pop() {
|
||||
if (!isEmpty()) {
|
||||
E datum = stackContent[total];
|
||||
stackContent[total--] = null;
|
||||
return datum;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void resize(int capacity) {
|
||||
Arrays.copyOf(stackContent, capacity);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return total == 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.baeldung.concurrent.semaphores;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SemaphoresManualTest {
|
||||
|
||||
// ========= login queue ======
|
||||
|
||||
@Test
|
||||
public void givenLoginQueue_whenReachLimit_thenBlocked() {
|
||||
final int slots = 10;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(slots);
|
||||
final LoginQueueUsingSemaphore loginQueue = new LoginQueueUsingSemaphore(slots);
|
||||
IntStream.range(0, slots)
|
||||
.forEach(user -> executorService.execute(loginQueue::tryLogin));
|
||||
executorService.shutdown();
|
||||
|
||||
assertEquals(0, loginQueue.availableSlots());
|
||||
assertFalse(loginQueue.tryLogin());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoginQueue_whenLogout_thenSlotsAvailable() {
|
||||
final int slots = 10;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(slots);
|
||||
final LoginQueueUsingSemaphore loginQueue = new LoginQueueUsingSemaphore(slots);
|
||||
IntStream.range(0, slots)
|
||||
.forEach(user -> executorService.execute(loginQueue::tryLogin));
|
||||
executorService.shutdown();
|
||||
|
||||
assertEquals(0, loginQueue.availableSlots());
|
||||
loginQueue.logout();
|
||||
assertTrue(loginQueue.availableSlots() > 0);
|
||||
assertTrue(loginQueue.tryLogin());
|
||||
}
|
||||
|
||||
// ========= delay queue =======
|
||||
|
||||
@Test
|
||||
public void givenDelayQueue_whenReachLimit_thenBlocked() {
|
||||
final int slots = 50;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(slots);
|
||||
final DelayQueueUsingTimedSemaphore delayQueue = new DelayQueueUsingTimedSemaphore(1, slots);
|
||||
IntStream.range(0, slots)
|
||||
.forEach(user -> executorService.execute(delayQueue::tryAdd));
|
||||
executorService.shutdown();
|
||||
|
||||
assertEquals(0, delayQueue.availableSlots());
|
||||
assertFalse(delayQueue.tryAdd());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDelayQueue_whenTimePass_thenSlotsAvailable() throws InterruptedException {
|
||||
final int slots = 50;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(slots);
|
||||
final DelayQueueUsingTimedSemaphore delayQueue = new DelayQueueUsingTimedSemaphore(1, slots);
|
||||
IntStream.range(0, slots)
|
||||
.forEach(user -> executorService.execute(delayQueue::tryAdd));
|
||||
executorService.shutdown();
|
||||
|
||||
assertEquals(0, delayQueue.availableSlots());
|
||||
Thread.sleep(1000);
|
||||
assertTrue(delayQueue.availableSlots() > 0);
|
||||
assertTrue(delayQueue.tryAdd());
|
||||
}
|
||||
|
||||
// ========== mutex ========
|
||||
|
||||
@Test
|
||||
public void whenMutexAndMultipleThreads_thenBlocked() throws InterruptedException {
|
||||
final int count = 5;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(count);
|
||||
final CounterUsingMutex counter = new CounterUsingMutex();
|
||||
IntStream.range(0, count)
|
||||
.forEach(user -> executorService.execute(() -> {
|
||||
try {
|
||||
counter.increase();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}));
|
||||
executorService.shutdown();
|
||||
|
||||
assertTrue(counter.hasQueuedThreads());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMutexAndMultipleThreads_ThenDelay_thenCorrectCount() throws InterruptedException {
|
||||
final int count = 5;
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(count);
|
||||
final CounterUsingMutex counter = new CounterUsingMutex();
|
||||
IntStream.range(0, count)
|
||||
.forEach(user -> executorService.execute(() -> {
|
||||
try {
|
||||
counter.increase();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}));
|
||||
executorService.shutdown();
|
||||
assertTrue(counter.hasQueuedThreads());
|
||||
Thread.sleep(5000);
|
||||
assertFalse(counter.hasQueuedThreads());
|
||||
assertEquals(count, counter.getCount());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.typeerasure;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TypeErasureUnitTest {
|
||||
|
||||
@Test(expected = ClassCastException.class)
|
||||
public void givenIntegerStack_whenStringPushedAndAssignPoppedValueToInteger_shouldFail() {
|
||||
IntegerStack integerStack = new IntegerStack(5);
|
||||
Stack stack = integerStack;
|
||||
stack.push("Hello");
|
||||
Integer data = integerStack.pop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnyArray_whenInvokedPrintArray_shouldSucceed() {
|
||||
Integer[] scores = new Integer[] { 100, 200, 10, 99, 20 };
|
||||
ArrayContentPrintUtil.printArray(scores);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -191,10 +191,12 @@
|
||||
<module>spring-security-mvc-login</module>
|
||||
<module>spring-security-mvc-persisted-remember-me</module>
|
||||
<module>spring-security-mvc-session</module>
|
||||
<module>spring-security-mvc-socket</module>
|
||||
<module>spring-security-rest-basic-auth</module>
|
||||
<module>spring-security-rest-custom</module>
|
||||
<module>spring-security-rest-full</module>
|
||||
<module>spring-security-rest</module>
|
||||
<module>spring-security-sso</module>
|
||||
<module>spring-security-x509</module>
|
||||
<module>spring-session</module>
|
||||
<module>spring-sleuth</module>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
.idea
|
||||
target
|
||||
*.iml
|
||||
out
|
||||
@@ -0,0 +1,2 @@
|
||||
### Relevant Articles:
|
||||
- [Intro to Security and WebSockets](http://www.baeldung.com/intro-to-security-and-websockets)
|
||||
@@ -0,0 +1,181 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.springsecuredsockets</groupId>
|
||||
<artifactId>spring-security-mvc-socket</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>1.0.0</version>
|
||||
<name>spring-security-mvc-socket</name>
|
||||
<properties>
|
||||
<springframework.version>4.3.8.RELEASE</springframework.version>
|
||||
<springsecurity.version>4.2.3.RELEASE</springsecurity.version>
|
||||
<jackson.version>2.8.7</jackson.version>
|
||||
<slf4j.version>1.7.25</slf4j.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Spring Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${springframework.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${springframework.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${springframework.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${springsecurity.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${springsecurity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Data -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.11.3.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>5.2.10.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.196</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Websockets -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-websocket</artifactId>
|
||||
<version>${springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-messaging</artifactId>
|
||||
<version>${springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-messaging</artifactId>
|
||||
<version>${springsecurity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Servlet -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp.jstl</groupId>
|
||||
<artifactId>jstl-api</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp</groupId>
|
||||
<artifactId>javax.servlet.jsp-api</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson Dependencies -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.tomcat.maven</groupId>
|
||||
<artifactId>tomcat7-maven-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<configuration>
|
||||
<path>/spring-security-mvc-socket</path>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<warSourceDirectory>src/main/webapp</warSourceDirectory>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<finalName>spring-security-mvc-socket</finalName>
|
||||
</build>
|
||||
</project>
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.springsecuredsockets.config;
|
||||
|
||||
import org.h2.tools.Server;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.resource.PathResourceResolver;
|
||||
import org.springframework.web.servlet.view.JstlView;
|
||||
import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@EnableJpaRepositories
|
||||
@ComponentScan("com.baeldung.springsecuredsockets")
|
||||
@Import({ SecurityConfig.class, DataStoreConfig.class, SocketBrokerConfig.class, SocketSecurityConfig.class })
|
||||
public class AppConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("index");
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
registry.addViewController("/secured/socket").setViewName("socket");
|
||||
registry.addViewController("/secured/success").setViewName("success");
|
||||
registry.addViewController("/denied").setViewName("denied");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UrlBasedViewResolver viewResolver() {
|
||||
final UrlBasedViewResolver bean = new UrlBasedViewResolver();
|
||||
bean.setPrefix("/WEB-INF/jsp/");
|
||||
bean.setSuffix(".jsp");
|
||||
bean.setViewClass(JstlView.class);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/", "/resources/")
|
||||
.setCachePeriod(3600)
|
||||
.resourceChain(true)
|
||||
.addResolver(new PathResourceResolver());
|
||||
}
|
||||
|
||||
// View H2
|
||||
@Bean(initMethod="start", destroyMethod="stop")
|
||||
public Server h2Console () throws SQLException {
|
||||
return Server.createWebServer("-web","-webAllowOthers","-webDaemon","-webPort", "8082");
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.baeldung.springsecuredsockets.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("com.baeldung.springsecuredsockets")
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaRepositories("com.baeldung.springsecuredsockets.repositories")
|
||||
public class DataStoreConfig {
|
||||
|
||||
//Configuration for embededded data store through H2
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.H2)
|
||||
.setName("socketDB")
|
||||
.addScript("classpath:schema.sql")
|
||||
.addScript("classpath:data.sql")
|
||||
.setScriptEncoding("UTF-8")
|
||||
.continueOnError(true)
|
||||
.ignoreFailedDrops(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JpaVendorAdapter jpaVendorAdapter() {
|
||||
final HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter();
|
||||
bean.setDatabase(Database.H2);
|
||||
bean.setGenerateDdl(true);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
|
||||
final LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
|
||||
bean.setDataSource(dataSource);
|
||||
bean.setJpaVendorAdapter(jpaVendorAdapter());
|
||||
bean.setPackagesToScan("com.baeldung.springsecuredsockets");
|
||||
|
||||
//Set properties on Hibernate
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
|
||||
properties.setProperty("hibernate.hbm2ddl.auto", "update");
|
||||
bean.setJpaProperties(properties);
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
|
||||
return new JpaTransactionManager(emf);
|
||||
}
|
||||
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package com.baeldung.springsecuredsockets.config;
|
||||
|
||||
import com.baeldung.springsecuredsockets.security.CustomAccessDeniedHandler;
|
||||
import com.baeldung.springsecuredsockets.security.CustomDaoAuthenticationProvider;
|
||||
import com.baeldung.springsecuredsockets.security.CustomLoginSuccessHandler;
|
||||
import com.baeldung.springsecuredsockets.security.CustomLogoutSuccessHandler;
|
||||
import com.baeldung.springsecuredsockets.security.CustomUserDetailsService;
|
||||
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.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
|
||||
/**
|
||||
* @EnableGlobalAuthentication annotates:
|
||||
* @EnableWebSecurity
|
||||
* @EnableWebMvcSecurity
|
||||
* @EnableGlobalMethodSecurity Passing in 'prePostEnabled = true' allows:
|
||||
* <p>
|
||||
* Pre/Post annotations such as:
|
||||
* @PreAuthorize("hasRole('ROLE_USER')")
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
@EnableWebSecurity
|
||||
@ComponentScan("com.baeldung.springsecuredsockets")
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private CustomUserDetailsService customUserDetailsService;
|
||||
|
||||
/**
|
||||
* Login, Logout, Success, and Access Denied beans/handlers
|
||||
*/
|
||||
|
||||
@Bean
|
||||
public AccessDeniedHandler accessDeniedHandler() {
|
||||
return new CustomAccessDeniedHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LogoutSuccessHandler logoutSuccessHandler() {
|
||||
return new CustomLogoutSuccessHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationSuccessHandler loginSuccessHandler() {
|
||||
return new CustomLoginSuccessHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication beans
|
||||
*/
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder encoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
final DaoAuthenticationProvider bean = new CustomDaoAuthenticationProvider();
|
||||
bean.setUserDetailsService(customUserDetailsService);
|
||||
bean.setPasswordEncoder(encoder());
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order of precedence is very important.
|
||||
* <p>
|
||||
* Matching occurs from top to bottom - so, the topmost match succeeds first.
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/", "/index", "/authenticate")
|
||||
.permitAll()
|
||||
.antMatchers("/secured/**/**",
|
||||
"/secured/success", "/secured/socket", "/secured/success")
|
||||
.authenticated()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/login").permitAll()
|
||||
.usernameParameter("username")
|
||||
.passwordParameter("password")
|
||||
.loginProcessingUrl("/authenticate")
|
||||
.successHandler(loginSuccessHandler())
|
||||
.failureUrl("/denied").permitAll()
|
||||
.and()
|
||||
.logout()
|
||||
.logoutSuccessHandler(logoutSuccessHandler())
|
||||
.and()
|
||||
/**
|
||||
* Applies to User Roles - not to login failures or unauthenticated access attempts.
|
||||
*/
|
||||
.exceptionHandling()
|
||||
.accessDeniedHandler(accessDeniedHandler())
|
||||
.and()
|
||||
.authenticationProvider(authenticationProvider());
|
||||
|
||||
/** Disabled for local testing */
|
||||
http
|
||||
.csrf().disable();
|
||||
|
||||
/** This is solely required to support H2 console viewing in Spring MVC with Spring Security */
|
||||
http
|
||||
.headers()
|
||||
.frameOptions()
|
||||
.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(authenticationProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.springsecuredsockets.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocketMessageBroker
|
||||
@ComponentScan("com.baeldung.springsecuredsockets.controllers")
|
||||
public class SocketBrokerConfig extends AbstractWebSocketMessageBrokerConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureMessageBroker(MessageBrokerRegistry config) {
|
||||
config.enableSimpleBroker("/secured/history");
|
||||
config.setApplicationDestinationPrefixes("/spring-security-mvc-socket");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry.addEndpoint("/secured/chat").withSockJS();
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.springsecuredsockets.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
|
||||
import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class SocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
|
||||
|
||||
@Override
|
||||
protected boolean sameOriginDisabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
|
||||
messages
|
||||
.simpDestMatchers("/secured/**").authenticated()
|
||||
.anyMessage().authenticated();
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.springsecuredsockets.config;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
|
||||
public class WebAppInitializer implements WebApplicationInitializer {
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext container) throws ServletException {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(AppConfig.class);
|
||||
context.setServletContext(container);
|
||||
|
||||
ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(context));
|
||||
servlet.setLoadOnStartup(1);
|
||||
servlet.addMapping("/");
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.springsecuredsockets.controllers;
|
||||
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
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;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Controller
|
||||
public class CsrfTokenController {
|
||||
@RequestMapping(value = "/csrf", method = RequestMethod.GET)
|
||||
public @ResponseBody
|
||||
String getCsrfToken(HttpServletRequest request) {
|
||||
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
return csrf.getToken();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user