This commit is contained in:
michal_aibin 2016-11-12 22:13:47 +01:00
commit 52a66320cb
72 changed files with 2736 additions and 104 deletions

View File

@ -2,4 +2,4 @@
## Core Java 9 Examples
http://inprogress.baeldung.com/java-9-new-features/
[Java 9 New Features](http://www.baeldung.com/new-java-9)

View File

@ -0,0 +1,119 @@
package com.baeldung.java9.language.stream;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.Integer.*;
import static org.junit.Assert.assertEquals;
public class StreamFeaturesTest {
public static class TakeAndDropWhileTest {
public Stream<String> getStreamAfterTakeWhileOperation() {
return Stream
.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10);
}
public Stream<String> getStreamAfterDropWhileOperation() {
return Stream
.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10)
.dropWhile(s -> !s.contains("sssss"));
}
@Test
public void testTakeWhileOperation() {
List<String> list = getStreamAfterTakeWhileOperation().collect(Collectors.toList());
assertEquals(10, list.size());
assertEquals("", list.get(0));
assertEquals("ss", list.get(2));
assertEquals("sssssssss", list.get(list.size() - 1));
}
@Test
public void testDropWhileOperation() {
List<String> list = getStreamAfterDropWhileOperation().collect(Collectors.toList());
assertEquals(5, list.size());
assertEquals("sssss", list.get(0));
assertEquals("sssssss", list.get(2));
assertEquals("sssssssss", list.get(list.size() - 1));
}
}
public static class IterateTest {
private Stream<Integer> getStream() {
return Stream.iterate(0, i -> i < 10, i -> i + 1);
}
@Test
public void testIterateOperation() {
List<Integer> list = getStream().collect(Collectors.toList());
assertEquals(10, list.size());
assertEquals(valueOf(0), list.get(0));
assertEquals(valueOf(5), list.get(5));
assertEquals(valueOf(9), list.get(list.size() - 1));
}
}
public static class OfNullableTest {
private List<String> collection = Arrays.asList("A", "B", "C");
private Map<String, Integer> map = new HashMap<>() {{
put("A", 10);
put("C", 30);
}};
private Stream<Integer> getStreamWithOfNullable() {
return collection.stream()
.flatMap(s -> Stream.ofNullable(map.get(s)));
}
private Stream<Integer> getStream() {
return collection.stream()
.flatMap(s -> {
Integer temp = map.get(s);
return temp != null ? Stream.of(temp) : Stream.empty();
});
}
private List<Integer> testOfNullableFrom(Stream<Integer> stream) {
List<Integer> list = stream.collect(Collectors.toList());
assertEquals(2, list.size());
assertEquals(valueOf(10), list.get(0));
assertEquals(valueOf(30), list.get(list.size() - 1));
return list;
}
@Test
public void testOfNullable() {
assertEquals(
testOfNullableFrom(getStream()),
testOfNullableFrom(getStreamWithOfNullable())
);
}
}
}

View File

View File

@ -35,4 +35,5 @@
- [Java 8 Streams Advanced](http://www.baeldung.com/java-8-streams)
- [Introduction to Thread Pools in Java](http://www.baeldung.com/thread-pool-java-and-guava)
- [Introduction to Java 8 Streams](http://www.baeldung.com/java-8-streams-introduction)
- [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join)
- [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join)
- [How to Print Screen in Java](http://www.baeldung.com/print-screen-in-java)

View File

@ -0,0 +1,97 @@
package com.baeldung.java.conversion;
import static org.junit.Assert.assertEquals;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.Month;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.junit.Test;
import com.baeldung.datetime.UseLocalDateTime;
public class StringConversionTest {
@Test
public void whenConvertedToInt_thenCorrect() {
assertEquals(Integer.parseInt("1"), 1);
}
@Test
public void whenConvertedToInteger_thenCorrect() {
assertEquals(Integer.valueOf("12").equals(12), true);
}
@Test
public void whenConvertedTolong_thenCorrect() {
assertEquals(Long.parseLong("12345"), 12345);
}
@Test
public void whenConvertedToLong_thenCorrect() {
assertEquals(Long.valueOf("14567").equals(14567L), true);
}
@Test
public void whenConvertedTodouble_thenCorrect() {
assertEquals(Double.parseDouble("1.4"), 1.4, 0.0);
}
@Test
public void whenConvertedToDouble_thenCorrect() {
assertEquals(Double.valueOf("145.67").equals(145.67d), true);
}
@Test
public void whenConvertedToByteArray_thenCorrect() throws UnsupportedEncodingException {
byte[] byteArray1 = new byte[] { 'a', 'b', 'c' };
String string = new String(byteArray1, "UTF-8");
assertEquals(Arrays.equals(string.getBytes(), byteArray1), true);
}
@Test
public void whenConvertedToboolean_thenCorrect() {
assertEquals(Boolean.parseBoolean("true"), true);
}
@Test
public void whenConvertedToBoolean_thenCorrect() {
assertEquals(Boolean.valueOf("true"), true);
}
@Test
public void whenConvertedToCharArray_thenCorrect() {
String str = "hello";
char[] charArray = { 'h', 'e', 'l', 'l', 'o' };
assertEquals(Arrays.equals(charArray, str.toCharArray()), true);
}
@Test
public void whenConvertedToDate_thenCorrect() throws ParseException {
String str = "15/10/2013";
SimpleDateFormat formatter = new SimpleDateFormat("dd/M/yyyy");
Date date1 = formatter.parse(str);
Calendar calendar = new GregorianCalendar(2013, 9, 15);
Date date2 = calendar.getTime();
assertEquals(date1.compareTo(date2), 0);
}
@Test
public void whenConvertedToLocalDateTime_thenCorrect() throws ParseException {
String str = "2007-12-03T10:15:30";
LocalDateTime localDateTime = new UseLocalDateTime().getLocalDateTimeUsingParseMethod(str);
assertEquals(localDateTime.getDayOfMonth(), 3);
assertEquals(localDateTime.getMonth(), Month.DECEMBER);
assertEquals(localDateTime.getYear(), 2007);
}
}

View File

@ -1,36 +1,28 @@
package org.baeldung.httpclient;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.*;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.junit.Test;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* This test requires a localhost server over HTTPS <br>
* It should only be manually run, not part of the automated build
@ -101,17 +93,9 @@ public class HttpsClientSslLiveTest {
}
@Test
public final void givenIgnoringCertificates_whenHttpsUrlIsConsumed_thenCorrect() throws IOException {
final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
SSLContext sslContext = null;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, acceptingTrustStrategy).build();
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
e.printStackTrace();
}
public final void givenIgnoringCertificates_whenHttpsUrlIsConsumed_thenCorrect() throws Exception {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, (certificate, authType) -> true).build();
final CloseableHttpClient client = HttpClients.custom().setSSLContext(sslContext).setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
final HttpGet httpGet = new HttpGet(HOST_WITH_SSL);

View File

@ -54,6 +54,11 @@
<artifactId>batik-transcoder</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
</dependencies>
<build>

View File

@ -95,6 +95,7 @@
<module>spring-data-neo4j</module>
<module>spring-data-redis</module>
<module>spring-data-rest</module>
<module>spring-data-solr</module>
<module>spring-dispatcher-servlet</module>
<module>spring-exceptions</module>
<module>spring-freemarker</module>
@ -132,6 +133,7 @@
<module>spring-security-rest-full</module>
<module>spring-security-rest</module>
<module>spring-security-x509</module>
<module>spring-session</module>
<module>spring-spel</module>
<module>spring-thymeleaf</module>
<module>spring-userservice</module>

View File

@ -0,0 +1,20 @@
package com.baeldung.camel.file;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class FileProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
String originalFileName = (String) exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
String changedFileName = dateFormat.format(date) + originalFileName;
exchange.getIn().setHeader(Exchange.FILE_NAME, changedFileName);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.camel.file;
import org.apache.camel.builder.RouteBuilder;
public class FileRouter extends RouteBuilder {
private static final String SOURCE_FOLDER = "src/test/source-folder";
private static final String DESTINATION_FOLDER = "src/test/destination-folder";
@Override
public void configure() throws Exception {
from("file://" + SOURCE_FOLDER + "?delete=true").process(new FileProcessor()).to("file://" + DESTINATION_FOLDER);
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<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-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="fileRouter" class="com.baeldung.camel.file.FileRouter" />
<bean id="fileProcessor" class="com.baeldung.camel.file.FileProcessor" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="fileRouter" />
</camelContext>
</beans>

View File

@ -1,39 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<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-3.1.xsd
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-3.1.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route customId="true" id="route1">
<route customId="true" id="route1">
<!-- Read files from input directory -->
<from uri="file://src/test/data/input"/>
<!-- Read files from input directory -->
<from uri="file://src/test/data/input" />
<!-- Transform content to UpperCase -->
<process ref="myFileProcessor"/>
<!-- Transform content to UpperCase -->
<process ref="myFileProcessor" />
<!-- Write converted file content -->
<to uri="file://src/test/data/outputUpperCase"/>
<!-- Write converted file content -->
<to uri="file://src/test/data/outputUpperCase" />
<!-- Transform content to LowerCase -->
<transform>
<simple>${body.toLowerCase()}</simple>
</transform>
<!-- Transform content to LowerCase -->
<transform>
<simple>${body.toLowerCase()}</simple>
</transform>
<!-- Write converted file content -->
<to uri="file://src/test/data/outputLowerCase"/>
<!-- Write converted file content -->
<to uri="file://src/test/data/outputLowerCase" />
<!-- Display process completion message on console -->
<transform>
<simple>.......... File content conversion completed ..........</simple>
</transform>
<to uri="stream:out"/>
<!-- Display process completion message on console -->
<transform>
<simple>.......... File content conversion completed ..........</simple>
</transform>
<to uri="stream:out" />
</route>
</route>
</camelContext>
</camelContext>
<bean id="myFileProcessor" class="com.baeldung.camel.processor.FileProcessor"/>
<bean id="myFileProcessor" class="com.baeldung.camel.processor.FileProcessor" />
</beans>

View File

@ -0,0 +1,68 @@
package org.apache.camel.file.processor;
import java.io.File;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.baeldung.camel.file.FileProcessor;
public class FileProcessorTest {
private static final long DURATION_MILIS = 10000;
private static final String SOURCE_FOLDER = "src/test/source-folder";
private static final String DESTINATION_FOLDER = "src/test/destination-folder";
@Before
public void setUp() throws Exception {
File sourceFolder = new File(SOURCE_FOLDER);
File destinationFolder = new File(DESTINATION_FOLDER);
cleanFolder(sourceFolder);
cleanFolder(destinationFolder);
sourceFolder.mkdirs();
File file1 = new File(SOURCE_FOLDER + "/File1.txt");
File file2 = new File(SOURCE_FOLDER + "/File2.txt");
file1.createNewFile();
file2.createNewFile();
}
private void cleanFolder(File folder) {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
file.delete();
}
}
}
}
@Test
public void moveFolderContentJavaDSLTest() throws Exception {
final CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("file://" + SOURCE_FOLDER + "?delete=true").process(new FileProcessor()).to("file://" + DESTINATION_FOLDER);
}
});
camelContext.start();
Thread.sleep(DURATION_MILIS);
camelContext.stop();
}
@Test
public void moveFolderContentSpringDSLTest() throws InterruptedException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("camel-context-test.xml");
Thread.sleep(DURATION_MILIS);
applicationContext.close();
}
}

View File

@ -14,5 +14,6 @@
- [Intro to Spring Cloud Netflix - Hystrix](http://www.baeldung.com/spring-cloud-netflix-hystrix)
- [Dockerizing a Spring Boot Application](http://www.baeldung.com/dockerizing-spring-boot-application)
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon)

View File

@ -11,6 +11,7 @@
<module>spring-cloud-eureka</module>
<module>spring-cloud-hystrix</module>
<module>spring-cloud-bootstrap</module>
<module>spring-cloud-ribbon-client</module>
</modules>
<packaging>pom</packaging>

View File

@ -0,0 +1,79 @@
<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.baeldung</groupId>
<artifactId>spring-cloud-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-cloud-ribbon-client</name>
<description>Introduction to Spring Cloud Rest Client with Netflix Ribbon</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,28 @@
package com.baeldung.spring.cloud.ribbon.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.PingUrl;
import com.netflix.loadbalancer.WeightedResponseTimeRule;
import com.netflix.loadbalancer.AvailabilityFilteringRule;
public class RibbonConfiguration {
@Autowired
IClientConfig ribbonClientConfig;
@Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
@Bean
public IRule ribbonRule(IClientConfig config) {
return new WeightedResponseTimeRule();
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.spring.cloud.ribbon.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@RestController
@RibbonClient(name = "ping-a-server", configuration = RibbonConfiguration.class)
public class ServerLocationApp {
@LoadBalanced
@Bean
RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Autowired
RestTemplate restTemplate;
@RequestMapping("/server-location")
public String serverLocation() {
String servLoc = this.restTemplate.getForObject("http://ping-server/locaus", String.class);
return servLoc;
}
public static void main(String[] args) {
SpringApplication.run(ServerLocationApp.class, args);
}
}

View File

@ -0,0 +1,13 @@
spring:
application:
name: spring-cloud-ribbon
server:
port: 8888
ping-server:
ribbon:
eureka:
enabled: false
listOfServers: localhost:9092,localhost:9999
ServerListRefreshInterval: 15000

View File

@ -0,0 +1,54 @@
package com.baeldung.spring.cloud.ribbon.client;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
@SuppressWarnings("unused")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ServerLocationApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ServerLocationAppTests {
ConfigurableApplicationContext application2;
ConfigurableApplicationContext application3;
@Before
public void startApps() {
this.application2 = startApp(9092);
this.application3 = startApp(9999);
}
@After
public void closeApps() {
this.application2.close();
this.application3.close();
}
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate testRestTemplate;
@Test
public void loadBalancingServersTest() throws InterruptedException {
ResponseEntity<String> response = this.testRestTemplate.getForEntity("http://localhost:" + this.port + "/server-location", String.class);
assertEquals(response.getBody(), "Australia");
}
private ConfigurableApplicationContext startApp(int port) {
return SpringApplication.run(TestConfig.class, "--server.port=" + port, "--spring.jmx.enabled=false");
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.spring.cloud.ribbon.client;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Configuration
@EnableAutoConfiguration
@RestController
public class TestConfig {
@RequestMapping(value = "/locaus")
public String locationAUSDetails() {
return "Australia";
}
}

69
spring-data-solr/pom.xml Normal file
View File

@ -0,0 +1,69 @@
<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.baeldung</groupId>
<artifactId>spring-data-solr</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-data-solr</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.2.5.RELEASE</spring.version>
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
<spring-data-solr>2.0.4.RELEASE</spring-data-solr>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>${spring-data-solr}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,25 @@
package com.baeldung.spring.data.solr.config;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.repository.config.EnableSolrRepositories;
@Configuration
@EnableSolrRepositories(basePackages = "com.baeldung.spring.data.solr.repository", namedQueriesLocation = "classpath:solr-named-queries.properties", multicoreSupport = true)
@ComponentScan
public class SolrConfig {
@Bean
public SolrClient solrClient() {
return new HttpSolrClient("http://localhost:8983/solr");
}
@Bean
public SolrTemplate solrTemplate(SolrClient client) throws Exception {
return new SolrTemplate(client);
}
}

View File

@ -0,0 +1,55 @@
package com.baeldung.spring.data.solr.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.Indexed;
import org.springframework.data.solr.core.mapping.SolrDocument;
@SolrDocument(solrCoreName = "product")
public class Product {
@Id
@Indexed(name = "id", type = "string")
private String id;
@Indexed(name = "name", type = "string")
private String name;
@Indexed(name = "category", type = "string")
private String category;
@Indexed(name = "description", type = "string")
private String description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.spring.data.solr.repository;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;
import com.baeldung.spring.data.solr.model.Product;
public interface ProductRepository extends SolrCrudRepository<Product, String> {
public List<Product> findByName(String name);
@Query("name:*?0* OR category:*?0* OR description:*?0*")
public Page<Product> findByCustomQuery(String searchTerm, Pageable pageable);
@Query(name = "Product.findByNamedQuery")
public Page<Product> findByNamedQuery(String searchTerm, Pageable pageable);
}

View File

@ -0,0 +1 @@
Product.findByNamedQuery=name:*?0* OR category:*?0* OR description:*?0*

View File

@ -0,0 +1,144 @@
package com.baeldung.spring.data.solr.repo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baeldung.spring.data.solr.config.SolrConfig;
import com.baeldung.spring.data.solr.model.Product;
import com.baeldung.spring.data.solr.repository.ProductRepository;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SolrConfig.class)
public class ProductRepositoryIntegrationTest {
@Autowired
private ProductRepository productRepository;
@Before
public void clearSolrData() {
productRepository.deleteAll();
}
@Test
public void whenSavingProduct_thenAvailableOnRetrieval() throws Exception {
final Product product = new Product();
product.setId("P000089998");
product.setName("Desk");
product.setCategory("Furniture");
product.setDescription("New Desk");
productRepository.save(product);
final Product retrievedProduct = productRepository.findOne(product.getId());
assertEquals(product.getId(), retrievedProduct.getId());
}
@Test
public void whenUpdatingProduct_thenChangeAvailableOnRetrieval() throws Exception {
final Product product = new Product();
product.setId("P0001");
product.setName("T-Shirt");
product.setCategory("Kitchen");
product.setDescription("New T-Shirt");
productRepository.save(product);
product.setCategory("Clothes");
productRepository.save(product);
final Product retrievedProduct = productRepository.findOne(product.getId());
assertEquals(product.getCategory(), retrievedProduct.getCategory());
}
@Test
public void whenDeletingProduct_thenNotAvailableOnRetrieval() throws Exception {
final Product product = new Product();
product.setId("P0001");
product.setName("Desk");
product.setCategory("Furniture");
product.setDescription("New Desk");
productRepository.save(product);
productRepository.delete(product);
Product retrievedProduct = productRepository.findOne(product.getId());
assertNull(retrievedProduct);
}
@Test
public void whenFindByName_thenAvailableOnRetrieval() throws Exception {
Product phone = new Product();
phone.setId("P0001");
phone.setName("Phone");
phone.setCategory("Electronics");
phone.setDescription("New Phone");
productRepository.save(phone);
List<Product> retrievedProducts = productRepository.findByName("Phone");
assertEquals(phone.getId(), retrievedProducts.get(0).getId());
}
@Test
public void whenSearchingProductsByQuery_thenAllMatchingProductsShouldAvialble() throws Exception {
final Product phone = new Product();
phone.setId("P0001");
phone.setName("Smart Phone");
phone.setCategory("Electronics");
phone.setDescription("New Item");
productRepository.save(phone);
final Product phoneCover = new Product();
phoneCover.setId("P0002");
phoneCover.setName("Cover");
phoneCover.setCategory("Phone");
phoneCover.setDescription("New Product");
productRepository.save(phoneCover);
final Product wirelessCharger = new Product();
wirelessCharger.setId("P0003");
wirelessCharger.setName("Charging Cable");
wirelessCharger.setCategory("Cable");
wirelessCharger.setDescription("Wireless Charger for Phone");
productRepository.save(wirelessCharger);
Page<Product> result = productRepository.findByCustomQuery("Phone", new PageRequest(0, 10));
assertEquals(3, result.getNumberOfElements());
}
@Test
public void whenSearchingProductsByNamedQuery_thenAllMatchingProductsShouldAvialble() throws Exception {
final Product phone = new Product();
phone.setId("P0001");
phone.setName("Smart Phone");
phone.setCategory("Electronics");
phone.setDescription("New Item");
productRepository.save(phone);
final Product phoneCover = new Product();
phoneCover.setId("P0002");
phoneCover.setName("Cover");
phoneCover.setCategory("Phone");
phoneCover.setDescription("New Product");
productRepository.save(phoneCover);
final Product wirelessCharger = new Product();
wirelessCharger.setId("P0003");
wirelessCharger.setName("Charging Cable");
wirelessCharger.setCategory("Cable");
wirelessCharger.setDescription("Wireless Charger for Phone");
productRepository.save(wirelessCharger);
Page<Product> result = productRepository.findByNamedQuery("one", new PageRequest(0, 10));
assertEquals(3, result.getNumberOfElements());
}
}

View File

@ -0,0 +1,3 @@
## Info ##
- The diagram is created with [yed](http://www.yworks.com/products/yed)

View File

@ -0,0 +1,372 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.16.2.1-->
<key attr.name="Beschreibung" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="600.0" width="1200.0" x="-187.59999999999997" y="60.18125000000006"/>
<y:Fill color="#FAFAFA" color2="#FAFAFA" transparent="false"/>
<y:BorderStyle color="#795548" type="dashed" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" backgroundColor="#FAFAFA" borderDistance="0.0" fontFamily="Roboto Mono" fontSize="20" fontStyle="plain" height="27.4375" horizontalTextPosition="center" iconTextGap="4" lineColor="#00695C" modelName="internal" modelPosition="t" textColor="#212121" verticalTextPosition="bottom" visible="true" width="340.0546875" x="429.97265625" y="0.0">Servlet Engine (e.g. Tomcat)</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="46" bottomF="45.78125" left="23" leftF="23.30000000000001" right="44" rightF="43.80000000000018" top="90" topF="89.98124999999999"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="473.0" y="280.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="21.4609375" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="65.201171875" x="-7.6005859375" y="0.0">Folder 1</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n0:">
<node id="n0::n0">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.onPageReference">
<y:Geometry height="180.0" width="270.0" x="683.5999999999999" y="192.60000000000005"/>
<y:Fill color="#212121" color2="#616161" transparent="false"/>
<y:BorderStyle color="#FAFAFA" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Roboto Mono" fontSize="21" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.609375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#FAFAFA" verticalTextPosition="bottom" visible="true" width="130.0205078125" x="69.98974609375" y="75.69531249999997">Controller<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.lang.Boolean" name="y.view.ShadowNodePainter.SHADOW_PAINTING" value="true"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n0::n1">
<data key="d6">
<y:GenericNode configuration="BevelNode2">
<y:Geometry height="34.0" width="69.0" x="464.29999999999995" y="274.6000000000002"/>
<y:Fill color="#FFC107" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" borderDistance="8.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#212121" verticalTextPosition="bottom" visible="true" width="58.0087890625" x="5.49560546875" y="4.453125">Model<y:LabelModel>
<y:SmartNodeLabelModel distance="8.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.lang.Boolean" name="ModernNodeShadow" value="true"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n0::n2">
<data key="d6">
<y:SVGNode>
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="-149.29999999999995" y="249.21899948120125"/>
<y:Fill color="#CCCCFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="26.277050018310547" y="70.76200103759766">
<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="0.5" offsetX="0.0" offsetY="4.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="1"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n0::n3">
<data key="d6">
<y:GenericNode configuration="BevelNode2">
<y:Geometry height="34.0" width="69.0" x="226.89999999999975" y="389.60000000000014"/>
<y:Fill color="#FFC107" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" borderDistance="8.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#212121" verticalTextPosition="bottom" visible="true" width="58.0087890625" x="5.49560546875" y="4.453125">Model<y:LabelModel>
<y:SmartNodeLabelModel distance="8.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.lang.Boolean" name="ModernNodeShadow" value="true"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n0::n4">
<data key="d4"/>
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.terminator">
<y:Geometry height="130.0" width="230.0" x="60.0" y="217.60000000000005"/>
<y:Fill color="#212121" color2="#616161" transparent="false"/>
<y:BorderStyle color="#FAFAFA" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Roboto Mono" fontSize="21" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.609375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#FAFAFA" verticalTextPosition="bottom" visible="true" width="218.23486328125" x="5.882568359375" y="50.69531249999997">DispatcherServlet<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.lang.Boolean" name="y.view.ShadowNodePainter.SHADOW_PAINTING" value="false"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
<node id="n0::n5">
<data key="d6">
<y:GenericNode configuration="com.yworks.flowchart.document">
<y:Geometry height="120.0" width="230.0" x="60.0" y="479.4000000000001"/>
<y:Fill color="#212121" color2="#616161" transparent="false"/>
<y:BorderStyle color="#FAFAFA" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Roboto Mono" fontSize="21" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="28.609375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#FAFAFA" verticalTextPosition="bottom" visible="true" width="167.82666015625" x="31.086669921875" y="45.6953125">View Template<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.lang.Boolean" name="y.view.ShadowNodePainter.SHADOW_PAINTING" value="true"/>
</y:StyleProperties>
</y:GenericNode>
</data>
</node>
</graph>
</node>
<edge id="e0" source="n0::n4" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e0" source="n0::n5" target="n0::n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-38.30000000000018" sy="-18.399999999999864" tx="-37.30000000000018" ty="3.6000000000001364"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.0" textColor="#212121" verticalTextPosition="bottom" visible="true" width="155.224609375" x="-179.1814364795589" y="-35.230035400390534">Return Control<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e1" source="n0::n4" target="n0::n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="48.69999999999982" sy="-5.399999999999864" tx="48.69999999999982" ty="-12.399999999999864"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="1.0" textColor="#212121" verticalTextPosition="bottom" visible="true" width="166.0263671875" x="24.00000305175763" y="96.57254638671884">Render Response<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e2" source="n0::n4" target="n0::n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="7.699999999999818" sy="-36.399999999999864" tx="3.699999999999818" ty="-36.399999999999864"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#212121" verticalTextPosition="bottom" visible="true" width="176.828125" x="119.53513793945308" y="-49.093746948242">Delegate Request<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e3" source="n0::n0" target="n0::n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="4.699999999999818" sy="29.600000000000136" tx="55.69999999999982" ty="29.600000000000136"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.0" textColor="#212121" verticalTextPosition="bottom" visible="true" width="328.0615234375" x="-388.2225097656251" y="23.99998779296891">Delegate Rendering of Response<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n0" target="n0::n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-409.1" sy="-128.18124999999975" tx="-6.5" ty="-35.39999999999975"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="20.0" fontFamily="Roboto Mono" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.0" textColor="#FAFAFA" verticalTextPosition="bottom" visible="true" width="4.0" x="-190.89999995231625" y="-171.81874999999994">
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e4" source="n0::n2" target="n0::n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="7.622949981689459" sy="-29.69998781681062" tx="-4.399999999999977" ty="-29.69998781681062"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.0" textColor="#212121" verticalTextPosition="bottom" visible="true" width="176.828125" x="4.834180450439476" y="-49.093746972084006">Incoming Request<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e5" source="n0::n4" target="n0::n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-16.399999999999977" sy="27.16233534321384" tx="28.290377113176618" ty="27.16233534321384"/>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.0" textColor="#212121" verticalTextPosition="bottom" visible="true" width="166.0263671875" x="-165.36247482299802" y="24.00000624165142">Return Response<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e6" source="n0::n0" target="n0::n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="912.5999999999999" y="125.60000000000002"/>
</y:Path>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="standard" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.25" textColor="#212121" verticalTextPosition="bottom" visible="true" width="155.224609375" x="-200.05571079132665" y="-142.76877441406248">Handle Request<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e7" source="n0::n0" target="n0::n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="862.5999999999999" y="459.2000000000001"/>
</y:Path>
<y:LineStyle color="#212121" type="line" width="4.0"/>
<y:Arrows source="standard" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="24.0" fontFamily="Roboto Mono" fontSize="18" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="25.09375" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.25" textColor="#212121" verticalTextPosition="bottom" visible="true" width="133.62109375" x="-61.31919657274125" y="63.13254394531259">Create Model<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources>
<y:Resource id="1">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"&gt;
&lt;g&gt;
&lt;radialGradient id="neck_x5F_white_1_" cx="28.0298" cy="-751.9429" r="11.4464" fx="25.7969" fy="-753.1596" gradientTransform="matrix(1 0 0 -1 0.1201 -706.5371)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#B38E5D"/&gt;
&lt;stop offset="1" style="stop-color:#805126"/&gt;
&lt;/radialGradient&gt;
&lt;path id="neck_x5F_white_2_" fill="url(#neck_x5F_white_1_)" stroke="#5B453B" stroke-miterlimit="10" d="M19.278,37.799h18.188
v13.23c-1.313,0.371-17.173,0.436-18.188,0.172V37.799z"/&gt;
&lt;radialGradient id="SVGID_1_" cx="27.481" cy="-760.3003" r="31.0533" fx="21.4231" fy="-763.6011" gradientTransform="matrix(1 0 0 -1 0.1201 -706.5371)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#B38E5D"/&gt;
&lt;stop offset="1" style="stop-color:#805126"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_1_)" stroke="#5B453B" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.7827" cy="-732.2632" r="23.424" fx="23.2131" fy="-734.753" gradientTransform="matrix(1 0 0 -1 0.1201 -706.5371)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#B38E5D"/&gt;
&lt;stop offset="1" style="stop-color:#805126"/&gt;
&lt;/radialGradient&gt;
&lt;path id="face_x5F_white_2_" fill="url(#face_x5F_white_1_)" stroke="#5B453B" stroke-miterlimit="10" d="M43.676,23.357
c0.086,10.199-6.738,18.52-15.246,18.586c-8.503,0.068-15.467-8.146-15.553-18.344C12.794,13.4,19.618,5.079,28.123,5.012
C36.627,4.945,43.59,13.158,43.676,23.357z"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="2941.4297" y1="5674.7988" x2="2965.0596" y2="5768.2505" gradientTransform="matrix(0.275 0 0 0.2733 -783.3976 -1542.678)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.42"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.12"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_2_" fill="url(#face_highlight_1_)" d="M27.958,6.333c-6.035,0.047-10.747,4.493-12.787,10.386
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247
c2.274-0.592,3.988-2.459,4.375-4.766c0.183-1.094,0.293-2.289,0.283-3.553C42.083,13.952,36.271,6.268,27.958,6.333z"/&gt;
&lt;path id="path9833_2_" fill="#4B4B4B" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.654,22.781
c15.665-0.703,12.289-10.48,9.658-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/&gt;
&lt;radialGradient id="collar_x5F_body_2_" cx="15.1587" cy="-763.7056" r="32.4004" gradientTransform="matrix(1 0 0 -1 0.1201 -706.5371)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#B0E8FF"/&gt;
&lt;stop offset="1" style="stop-color:#74AEEE"/&gt;
&lt;/radialGradient&gt;
&lt;path id="collar_x5F_body_1_" fill="url(#collar_x5F_body_2_)" stroke="#5491CF" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494
h48.51c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146
c-1.771,1.655-5.61,2.802-10.063,2.802c-4.453,0-8.292-1.146-10.063-2.802c0,0-5.755,0.586-11.189,6.021
C1.378,56.689,0.5,62.768,0.5,62.768z"/&gt;
&lt;radialGradient id="collar_x5F_r_2_" cx="31.5" cy="-753.832" r="9.2834" gradientTransform="matrix(1 0 0 -1 0.1201 -706.5371)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#80CCFF"/&gt;
&lt;stop offset="1" style="stop-color:#74AEEE"/&gt;
&lt;/radialGradient&gt;
&lt;path id="collar_x5F_r_1_" fill="url(#collar_x5F_r_2_)" stroke="#5491CF" d="M38.159,41.381c0,0-0.574,2.369-3.013,4.441
c-2.108,1.795-5.783,2.072-5.783,2.072l3.974,6.217c0,0,2.957-1.637,5.009-3.848c1.922-2.072,1.37-5.479,1.37-5.479L38.159,41.381z
"/&gt;
&lt;radialGradient id="collar_x5F_l_2_" cx="19.1377" cy="-753.873" r="9.2837" gradientTransform="matrix(1 0 0 -1 0.1201 -706.5371)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#80CCFF"/&gt;
&lt;stop offset="1" style="stop-color:#74AEEE"/&gt;
&lt;/radialGradient&gt;
&lt;path id="collar_x5F_l_1_" fill="url(#collar_x5F_l_2_)" stroke="#5491CF" d="M18.63,41.422c0,0,0.576,2.369,3.012,4.441
c2.109,1.793,5.785,2.072,5.785,2.072l-3.974,6.217c0,0-2.957-1.637-5.007-3.85c-1.922-2.072-1.37-5.48-1.37-5.48L18.63,41.422z"/&gt;
&lt;radialGradient id="Knob2_2_" cx="27.8872" cy="9.9414" r="0.9669" gradientTransform="matrix(1 0 0 -1 0.04 66.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#80CCFF"/&gt;
&lt;stop offset="1" style="stop-color:#74AEEE"/&gt;
&lt;/radialGradient&gt;
&lt;circle id="Knob2_1_" fill="url(#Knob2_2_)" stroke="#5491CF" cx="28.258" cy="56.254" r="0.584"/&gt;
&lt;radialGradient id="Knob1_2_" cx="27.9253" cy="3.6973" r="0.9669" gradientTransform="matrix(1 0 0 -1 0.04 66.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#80CCFF"/&gt;
&lt;stop offset="1" style="stop-color:#74AEEE"/&gt;
&lt;/radialGradient&gt;
&lt;circle id="Knob1_1_" fill="url(#Knob1_2_)" stroke="#5491CF" cx="28.296" cy="62.499" r="0.584"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -0,0 +1,13 @@
## Spring MVC Email
Example Spring MVC project to send email from web form.
### Installing and Running
Just run the Spring Boot application.
Type http://localhost:8080 in your browser to open the application.
### Sending test emails
Follow UI links to send simple email, email using template or email with attachment.

55
spring-mvc-email/pom.xml Normal file
View File

@ -0,0 +1,55 @@
<?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>org.baeldung.spring</groupId>
<artifactId>SpringMVCEmail</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath></relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Mail dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<!-- The following two dependencies included to render jsp pages -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>8.5.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,12 @@
package com.baeldung.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.spring.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
/**
* Created with IntelliJ IDEA.
* User: Olga
*/
@Configuration
@ComponentScan("com.baeldung.spring")
@EnableWebMvc //tha same as <mvc:annotation-driven/>
public class AppConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Bean
public UrlBasedViewResolver urlBasedViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setOrder(0);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setCache(false);
resolver.setViewClass(JstlView.class);
return resolver;
}
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setOrder(1);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
@Bean
public SimpleMailMessage templateSimpleMessage() {
SimpleMailMessage message = new SimpleMailMessage();
message.setText("This is the test email template for your email:\n%s\n");
return message;
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.spring.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Created with IntelliJ IDEA.
* User: Olga
*/
@Controller
@RequestMapping({"/","/home"})
public class HomeController {
@RequestMapping(method = RequestMethod.GET)
public String showHomePage() {
return "home";
}
}

View File

@ -0,0 +1,131 @@
package com.baeldung.spring.controllers;
import com.baeldung.spring.mail.EmailServiceImpl;
import com.baeldung.spring.web.dto.MailObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Created by Olga on 7/20/2016.
*/
@Controller
@RequestMapping("/mail")
public class MailController {
@Autowired
public EmailServiceImpl emailService;
@Value("${attachment.invoice}")
private String attachmentPath;
@Autowired
@Qualifier("templateSimpleMessage")
public SimpleMailMessage template;
private static final Map<String, Map<String, String>> labels;
static {
labels = new HashMap<>();
//Simple email
Map<String, String> props = new HashMap<>();
props.put("headerText", "Send Simple Email");
props.put("messageLabel", "Message");
props.put("additionalInfo", "");
labels.put("send", props);
//Email with template
props = new HashMap<>();
props.put("headerText", "Send Email Using Template");
props.put("messageLabel", "Template Parameter");
props.put("additionalInfo",
"The parameter value will be added to the following message template:<br>" +
"<b>This is the test email template for your email:<br>'Template Parameter'</b>"
);
labels.put("sendTemplate", props);
//Email with attachment
props = new HashMap<>();
props.put("headerText", "Send Email With Attachment");
props.put("messageLabel", "Message");
props.put("additionalInfo", "To make sure that you send an attachment with this email, change the value for the 'attachment.invoice' in the application.properties file to the path to the attachment.");
labels.put("sendAttachment", props);
}
@RequestMapping(value = {"/send", "/sendTemplate", "/sendAttachment"}, method = RequestMethod.GET)
public String createMail(Model model,
HttpServletRequest request) {
String action = request.getRequestURL().substring(
request.getRequestURL().lastIndexOf("/") + 1
);
Map<String, String> props = labels.get(action);
Set<String> keys = props.keySet();
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
model.addAttribute(key, props.get(key));
}
model.addAttribute("mailObject", new MailObject());
return "mail/send";
}
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String createMail(Model model,
@ModelAttribute("mailObject") @Valid MailObject mailObject,
Errors errors) {
if (errors.hasErrors()) {
return "mail/send";
}
emailService.sendSimpleMessage(mailObject.getTo(),
mailObject.getSubject(), mailObject.getText());
return "redirect:/home";
}
@RequestMapping(value = "/sendTemplate", method = RequestMethod.POST)
public String createMailWithTemplate(Model model,
@ModelAttribute("mailObject") @Valid MailObject mailObject,
Errors errors) {
if (errors.hasErrors()) {
return "mail/send";
}
emailService.sendSimpleMessageUsingTemplate(mailObject.getTo(),
mailObject.getSubject(),
template,
mailObject.getText());
return "redirect:/home";
}
@RequestMapping(value = "/sendAttachment", method = RequestMethod.POST)
public String createMailWithAttachment(Model model,
@ModelAttribute("mailObject") @Valid MailObject mailObject,
Errors errors) {
if (errors.hasErrors()) {
return "mail/send";
}
emailService.sendMessageWithAttachment(
mailObject.getTo(),
mailObject.getSubject(),
mailObject.getText(),
attachmentPath
);
return "redirect:/home";
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.spring.mail;
import org.springframework.mail.SimpleMailMessage;
/**
* Created by Olga on 8/22/2016.
*/
public interface EmailService {
void sendSimpleMessage(String to,
String subject,
String text);
void sendSimpleMessageUsingTemplate(String to,
String subject,
SimpleMailMessage template,
String ...templateArgs);
void sendMessageWithAttachment(String to,
String subject,
String text,
String pathToAttachment);
}

View File

@ -0,0 +1,68 @@
package com.baeldung.spring.mail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
/**
* Created by Olga on 7/15/2016.
*/
@Component
public class EmailServiceImpl implements EmailService {
@Autowired
public JavaMailSender emailSender;
public void sendSimpleMessage(String to, String subject, String text) {
try {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
emailSender.send(message);
} catch (MailException exception) {
exception.printStackTrace();
}
}
@Override
public void sendSimpleMessageUsingTemplate(String to,
String subject,
SimpleMailMessage template,
String ...templateArgs) {
String text = String.format(template.getText(), templateArgs);
sendSimpleMessage(to, subject, text);
}
@Override
public void sendMessageWithAttachment(String to,
String subject,
String text,
String pathToAttachment) {
try {
MimeMessage message = emailSender.createMimeMessage();
// pass 'true' to the constructor to create a multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file = new FileSystemResource(new File(pathToAttachment));
helper.addAttachment("Invoice", file);
emailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.spring.web.dto;
import org.hibernate.validator.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* Created by Olga on 7/20/2016.
*/
public class MailObject {
@Email
@NotNull
@Size(min = 1, message = "Please, set an email address to send the message to it")
private String to;
private String subject;
private String text;
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd"
version="6">
<module id="SpringMVCEmail">
<web>
<web-uri>SpringMVCEmail.war</web-uri>
<context-root>SpringMVCEmail</context-root>
</web>
</module>
<module id="SpringMVCEmail-Web">
<web>
<web-uri>web.war</web-uri>
<context-root>SpringMVCEmailWeb</context-root>
</web>
</module>
</application>

View File

@ -0,0 +1,20 @@
# Gmail SMTP
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=username
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
# Amazon SES SMTP
#spring.mail.host=email-smtp.us-west-2.amazonaws.com
#spring.mail.username=username
#spring.mail.password=password
#spring.mail.properties.mail.transport.protocol=smtp
#spring.mail.properties.mail.smtp.port=25
#spring.mail.properties.mail.smtp.auth=true
#spring.mail.properties.mail.smtp.starttls.enable=true
#spring.mail.properties.mail.smtp.starttls.required=true
# path to attachment file
attachment.invoice=path_to_file

View File

@ -0,0 +1,43 @@
<%--
Created by IntelliJ IDEA.
User: Olga
Date: 1/19/16
Time: 3:53 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Home Page</title>
</head>
<body>
<div>
<div>
<h4>Select any of the options below to send sample email:</h4>
<form method="get" style="width: 200px;">
<fieldset style="border: none; padding-left: 0px; padding-top: 0px">
<table>
<tr>
<td>
<input type="submit" formaction="mail/send" value="Send Simple Email">
</td>
</tr>
<tr>
<td>
<input type="submit" formaction="mail/sendTemplate" value="Send Email Using Template">
</td>
</tr>
<tr>
<td>
<input type="submit" formaction="mail/sendAttachment" value="Send Email With Attachment">
</td>
</tr>
</table>
</fieldset>
</form>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,58 @@
<%--
Created by IntelliJ IDEA.
User: Olga
Date: 7/20/2016
Time: 1:47 PM
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>Send Email</title>
</head>
<body>
<div>
<h3>${headerText}</h3>
<form:form method="POST" modelAttribute="mailObject" >
<fieldset>
<div style="float:left;">
<table cellspacing="0" width="300">
<tr>
<th><label for="input_to">To</label></th>
<td><form:input path="to" id="input_to" type="email"/>
<small>Enter email address</small><br/>
<form:errors path="to" cssStyle="color:red;font-size:small"/>
</td>
</tr>
<tr>
<th><label for="input_subject">Subject</label></th>
<td><form:input path="subject" id="input_subject"/>
<small>Enter the subject</small><br/>
<form:errors path="subject" cssStyle="color:red;font-size:small"/>
</td>
</tr>
<tr>
<th><label for="input_text">${messageLabel}:</label></th>
<td><form:textarea path="text"
rows="5" cols="50"
id="input_text"/>
<form:errors path="text" cssStyle="color:red;font-size:small"/>
</td>
</tr>
<tr>
<th></th>
<td>
<input type="submit" value="Send">
</td>
</tr>
</table>
</div>
<div style="float:left; word-wrap: break-word; margin-left: 50px; width: 400px; color: grey">
${additionalInfo}
</div>
</fieldset>
</form:form>
</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>simpleweb</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.baeldung.spring.app.config.AppConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>simpleweb</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -56,13 +56,10 @@ public class OkHttpFileUploadingLiveTest {
.build();
ProgressRequestWrapper.ProgressListener listener = new ProgressRequestWrapper.ProgressListener() {
ProgressRequestWrapper.ProgressListener listener = (bytesWritten, contentLength) -> {
public void onRequestProgress(long bytesWritten, long contentLength) {
float percentage = 100f * bytesWritten / contentLength;
assertFalse(Float.compare(percentage, 100) > 0);
}
float percentage = 100f * bytesWritten / contentLength;
assertFalse(Float.compare(percentage, 100) > 0);
};
ProgressRequestWrapper countingBody = new ProgressRequestWrapper(requestBody, listener);

View File

@ -1,18 +1,13 @@
package org.baeldung.okhttp;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import okhttp3.*;
import org.junit.Test;
import java.io.IOException;
import org.junit.Test;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class OkHttpGetLiveTest {
@ -54,7 +49,7 @@ public class OkHttpGetLiveTest {
}
@Test
public void whenAsynchronousGetRequest_thenCorrect() {
public void whenAsynchronousGetRequest_thenCorrect() throws InterruptedException {
OkHttpClient client = new OkHttpClient();
@ -65,14 +60,15 @@ public class OkHttpGetLiveTest {
Call call = client.newCall(request);
call.enqueue(new Callback() {
public void onResponse(Call call, Response response) throws IOException {
assertThat(response.code(), equalTo(200));
System.out.println("OK");
}
public void onFailure(Call call, IOException e) {
fail();
}
});
Thread.sleep(3000);
}
}

View File

@ -1,21 +1,16 @@
package org.baeldung.okhttp;
import okhttp3.*;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpMiscLiveTest {
private static final String BASE_URL = "http://localhost:8080/spring-rest";
@ -37,7 +32,7 @@ public class OkHttpMiscLiveTest {
response.close();
}
@Test
@Test(expected = IOException.class)
public void whenCancelRequest_thenCorrect() throws IOException {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
@ -49,30 +44,22 @@ public class OkHttpMiscLiveTest {
.build();
final int seconds = 1;
final long startNanos = System.nanoTime();
final Call call = client.newCall(request);
// Schedule a job to cancel the call in 1 second.
executor.schedule(new Runnable() {
public void run() {
executor.schedule(() -> {
logger.debug("Canceling call: " + (System.nanoTime() - startNanos) / 1e9f);
call.cancel();
logger.debug("Canceled call: " + (System.nanoTime() - startNanos) / 1e9f);
logger.debug("Canceling call: " + (System.nanoTime() - startNanos) / 1e9f);
call.cancel();
logger.debug("Canceled call: " + (System.nanoTime() - startNanos) / 1e9f);
}
}, seconds, TimeUnit.SECONDS);
try {
logger.debug("Executing call: " + (System.nanoTime() - startNanos) / 1e9f);
Response response = call.execute();
logger.debug("Call was expected to fail, but completed: " + (System.nanoTime() - startNanos) / 1e9f, response);
} catch (IOException e) {
logger.debug("Call failed as expected: " + (System.nanoTime() - startNanos) / 1e9f, e);
}
logger.debug("Executing call: " + (System.nanoTime() - startNanos) / 1e9f);
Response response = call.execute();
logger.debug("Call completed: " + (System.nanoTime() - startNanos) / 1e9f, response);
}
@Test

View File

@ -0,0 +1,71 @@
<?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.baeldung</groupId>
<artifactId>jetty-session-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,24 @@
package com.baeldung.spring.session.tomcatex;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class JettyWebApplication {
public static void main(String[] args) {
SpringApplication.run(JettyWebApplication.class, args);
}
@RequestMapping
public String helloJetty() {
return "hello Jetty";
}
@RequestMapping("/test")
public String lksjdf() {
return "";
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.spring.session.tomcatex;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests().anyRequest().hasRole("ADMIN");
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.spring.session.tomcatex;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;
@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
@Bean
public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy();
}
}

View File

@ -0,0 +1,3 @@
server.port=8081
spring.redis.host=localhost
spring.redis.port=6379

22
spring-session/pom.xml Normal file
View File

@ -0,0 +1,22 @@
<?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>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>spring-session</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>jetty-session-demo</module>
<module>tomcat-session-demo</module>
</modules>
</project>

View File

@ -0,0 +1,66 @@
<?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.baeldung</groupId>
<artifactId>tomcat-session-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,31 @@
package com.baeldung.spring.session.tomcatex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/tomcat").hasRole("USER")
.antMatchers("/tomcat/admin").hasRole("ADMIN")
.anyRequest().authenticated();
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.spring.session.tomcatex;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
}

View File

@ -0,0 +1,29 @@
package com.baeldung.spring.session.tomcatex;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class TomcatWebApplication {
public static void main(String[] args) {
SpringApplication.run(TomcatWebApplication.class, args);
}
@RequestMapping
public String helloDefault() {
return "hello default";
}
@RequestMapping("/tomcat")
public String helloTomcat() {
return "hello tomcat";
}
@RequestMapping("/tomcat/admin")
public String helloTomcatAdmin() {
return "hello tomcat admin";
}
}

View File

@ -0,0 +1,2 @@
spring.redis.host=localhost
spring.redis.port=6379

169
spring-social-login/pom.xml Normal file
View File

@ -0,0 +1,169 @@
<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>
<artifactId>spring-social-login</artifactId>
<name>spring-social-login</name>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath></relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-facebook</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
</dependencies>
<build>
<finalName>spring-social-login</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<java.version>1.8</java.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
</properties>
</project>

View File

@ -0,0 +1,18 @@
package org.baeldung.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EnableJpaRepositories("org.baeldung.persistence.dao")
@EntityScan("org.baeldung.persistence.model")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,61 @@
package org.baeldung.config;
import org.baeldung.security.FacebookSignInAdapter;
import org.baeldung.security.FacebookConnectionSignup;
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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.mem.InMemoryUsersConnectionRepository;
import org.springframework.social.connect.web.ProviderSignInController;
@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = { "org.baeldung.security" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private ConnectionFactoryLocator connectionFactoryLocator;
@Autowired
private UsersConnectionRepository usersConnectionRepository;
@Autowired
private FacebookConnectionSignup facebookConnectionSignup;
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login*","/signin/**","/signup/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout();
} // @formatter:on
@Bean
// @Primary
public ProviderSignInController providerSignInController() {
((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter());
}
}

View File

@ -0,0 +1,39 @@
package org.baeldung.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
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;
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Override
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/").setViewName("forward:/index");
registry.addViewController("/index");
registry.addViewController("/login");
}
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}

View File

@ -0,0 +1,10 @@
package org.baeldung.persistence.dao;
import org.baeldung.persistence.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(final String username);
}

View File

@ -0,0 +1,55 @@
package org.baeldung.persistence.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false, unique = true)
private String username;
private String password;
public User() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("User [id=").append(id).append(", username=").append(username).append(", password=").append(password).append("]");
return builder.toString();
}
}

View File

@ -0,0 +1,28 @@
package org.baeldung.security;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import org.baeldung.persistence.dao.UserRepository;
import org.baeldung.persistence.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.ConnectionSignUp;
import org.springframework.stereotype.Service;
@Service
public class FacebookConnectionSignup implements ConnectionSignUp {
@Autowired
private UserRepository userRepository;
@Override
public String execute(Connection<?> connection) {
System.out.println("signup === ");
final User user = new User();
user.setUsername(connection.getDisplayName());
user.setPassword(randomAlphabetic(8));
userRepository.save(user);
return user.getUsername();
}
}

View File

@ -0,0 +1,21 @@
package org.baeldung.security;
import java.util.Arrays;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.web.SignInAdapter;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.NativeWebRequest;
@Service
public class FacebookSignInAdapter implements SignInAdapter {
@Override
public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
System.out.println(" ====== Sign In adapter");
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(connection.getDisplayName(), null, Arrays.asList(new SimpleGrantedAuthority("FACEBOOK_USER"))));
return null;
}
}

View File

@ -0,0 +1,34 @@
package org.baeldung.security;
import java.util.Arrays;
import org.baeldung.persistence.dao.UserRepository;
import org.baeldung.persistence.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
public MyUserDetailsService() {
super();
}
// API
@Override
public UserDetails loadUserByUsername(final String username) {
final User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true, true, true, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
}
}

View File

@ -0,0 +1,3 @@
spring.social.facebook.appId=1715784745414888
spring.social.facebook.appSecret=abefd6497e9cc01ad03be28509617bf0
spring.thymeleaf.cache=false

View File

@ -0,0 +1 @@
insert into User (id, username, password) values (1,'john', '123');

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Spring Social Login</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"/>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" th:href="@{/}">Spring Social Login</a>
</div>
<p class="navbar-text navbar-right">
<span sec:authentication="name">Username</span> &nbsp; &nbsp; &nbsp;
<a th:href="@{/logout}">Logout</a>&nbsp; &nbsp; &nbsp;
</p>
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<h1 class="col-sm-12">Welcome, <span sec:authentication="name">Username</span></h1>
<p class="col-sm-12 text-muted" sec:authentication="authorities">User authorities</p>
</div>
</body>
</html>

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Spring Social Login</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div th:if="${param.logout}" class="alert alert-info">You have been logged out</div>
<div th:if="${param.error}" class="alert alert-danger">There was an error, please try again</div>
<h1 class="col-sm-12">Login</h1>
<form th:action="@{/login}" method="POST" >
<div class="row col-sm-6">
<div class="form-group">
<label class="col-sm-3">Username</label>
<span class="col-sm-9"><input class="form-control" type="text" name="username" /></span>
</div>
<br/>
<div class="form-group">
<label class="col-sm-3">Password</label>
<span class="col-sm-9"><input class="form-control" type="password" name="password" /></span>
</div>
<div class="col-sm-12">
<input type="submit" value="Login" class="btn btn-default" />
</div>
</div>
</form>
<div class="clearfix"></div>
<br/>
<br/>
<div class="col-sm-12">
<form action="/signin/facebook" method="POST">
<input type="hidden" name="scope" value="public_profile" />
<input type="submit" value="Login using Facebook" class="btn btn-primary" />
</form>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,18 @@
package org.baeldung.test;
import org.baeldung.config.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationIntegrationTest {
@Test
public void whenLoadApplication_thenSuccess() {
}
}