diff --git a/core-java-9/README.md b/core-java-9/README.md index b5d4dbef95..fbe5f908aa 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -2,4 +2,4 @@ ## Core Java 9 Examples -http://inprogress.baeldung.com/java-9-new-features/ \ No newline at end of file +[Java 9 New Features](http://www.baeldung.com/new-java-9) diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesTest.java new file mode 100644 index 0000000000..a260e84164 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/language/stream/StreamFeaturesTest.java @@ -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 getStreamAfterTakeWhileOperation() { + return Stream + .iterate("", s -> s + "s") + .takeWhile(s -> s.length() < 10); + } + + public Stream getStreamAfterDropWhileOperation() { + return Stream + .iterate("", s -> s + "s") + .takeWhile(s -> s.length() < 10) + .dropWhile(s -> !s.contains("sssss")); + } + + @Test + public void testTakeWhileOperation() { + List 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 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 getStream() { + return Stream.iterate(0, i -> i < 10, i -> i + 1); + } + + @Test + public void testIterateOperation() { + List 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 collection = Arrays.asList("A", "B", "C"); + private Map map = new HashMap<>() {{ + put("A", 10); + put("C", 30); + }}; + + private Stream getStreamWithOfNullable() { + return collection.stream() + .flatMap(s -> Stream.ofNullable(map.get(s))); + } + + private Stream getStream() { + return collection.stream() + .flatMap(s -> { + Integer temp = map.get(s); + return temp != null ? Stream.of(temp) : Stream.empty(); + }); + } + + private List testOfNullableFrom(Stream stream) { + List 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()) + ); + + } + + } + +} diff --git a/core-java/0.12457740242410742 b/core-java/0.12457740242410742 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/README.md b/core-java/README.md index 48f0677461..49317bf369 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -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) \ No newline at end of file +- [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) diff --git a/core-java/src/test/java/com/baeldung/java/conversion/StringConversionTest.java b/core-java/src/test/java/com/baeldung/java/conversion/StringConversionTest.java new file mode 100644 index 0000000000..d4786f54ac --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/conversion/StringConversionTest.java @@ -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); + } +} diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java b/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java index fb272b0a33..278cdb3556 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java +++ b/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java @@ -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
* 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); diff --git a/pdf/pom.xml b/pdf/pom.xml index be1e9822e2..311265880d 100644 --- a/pdf/pom.xml +++ b/pdf/pom.xml @@ -54,6 +54,11 @@ batik-transcoder 1.8 + + org.apache.poi + poi-ooxml + 3.15 + diff --git a/pom.xml b/pom.xml index d8830e2a59..bd626b3ad0 100644 --- a/pom.xml +++ b/pom.xml @@ -95,6 +95,7 @@ spring-data-neo4j spring-data-redis spring-data-rest + spring-data-solr spring-dispatcher-servlet spring-exceptions spring-freemarker @@ -132,6 +133,7 @@ spring-security-rest-full spring-security-rest spring-security-x509 + spring-session spring-spel spring-thymeleaf spring-userservice diff --git a/spring-apache-camel/src/main/java/com/baeldung/camel/file/FileProcessor.java b/spring-apache-camel/src/main/java/com/baeldung/camel/file/FileProcessor.java new file mode 100644 index 0000000000..1ea2cad188 --- /dev/null +++ b/spring-apache-camel/src/main/java/com/baeldung/camel/file/FileProcessor.java @@ -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); + } + +} diff --git a/spring-apache-camel/src/main/java/com/baeldung/camel/file/FileRouter.java b/spring-apache-camel/src/main/java/com/baeldung/camel/file/FileRouter.java new file mode 100644 index 0000000000..5216c9a595 --- /dev/null +++ b/spring-apache-camel/src/main/java/com/baeldung/camel/file/FileRouter.java @@ -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); + } + +} diff --git a/spring-apache-camel/src/main/resources/camel-context-test.xml b/spring-apache-camel/src/main/resources/camel-context-test.xml new file mode 100644 index 0000000000..e6435db9e5 --- /dev/null +++ b/spring-apache-camel/src/main/resources/camel-context-test.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/spring-apache-camel/src/main/resources/camel-context.xml b/spring-apache-camel/src/main/resources/camel-context.xml index 0c10e0ecef..63ef406fdf 100644 --- a/spring-apache-camel/src/main/resources/camel-context.xml +++ b/spring-apache-camel/src/main/resources/camel-context.xml @@ -1,39 +1,39 @@ - + - + - - + + - - + + - - + + - - - ${body.toLowerCase()} - + + + ${body.toLowerCase()} + - - + + - - - .......... File content conversion completed .......... - - + + + .......... File content conversion completed .......... + + - + - + - + \ No newline at end of file diff --git a/spring-apache-camel/src/test/java/org/apache/camel/file/processor/FileProcessorTest.java b/spring-apache-camel/src/test/java/org/apache/camel/file/processor/FileProcessorTest.java new file mode 100644 index 0000000000..3d63f614e0 --- /dev/null +++ b/spring-apache-camel/src/test/java/org/apache/camel/file/processor/FileProcessorTest.java @@ -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(); + + } +} \ No newline at end of file diff --git a/spring-cloud/README.md b/spring-cloud/README.md index 3e8cd21b82..60acdaeed5 100644 --- a/spring-cloud/README.md +++ b/spring-cloud/README.md @@ -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) diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 2349613def..455a5b876b 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -11,6 +11,7 @@ spring-cloud-eureka spring-cloud-hystrix spring-cloud-bootstrap + spring-cloud-ribbon-client pom diff --git a/spring-cloud/spring-cloud-ribbon-client/pom.xml b/spring-cloud/spring-cloud-ribbon-client/pom.xml new file mode 100644 index 0000000000..c597c5ab8e --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/pom.xml @@ -0,0 +1,79 @@ + + 4.0.0 + com.baeldung + spring-cloud-ribbon + 0.0.1-SNAPSHOT + jar + spring-cloud-ribbon-client + Introduction to Spring Cloud Rest Client with Netflix Ribbon + + + org.springframework.boot + spring-boot-starter-parent + 1.4.1.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.cloud + spring-cloud-starter-ribbon + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Camden.SR1 + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/RibbonConfiguration.java b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/RibbonConfiguration.java new file mode 100644 index 0000000000..59998432ad --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/RibbonConfiguration.java @@ -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(); + } + +} diff --git a/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java new file mode 100644 index 0000000000..6105e2c489 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/src/main/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationApp.java @@ -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); + } +} diff --git a/spring-cloud/spring-cloud-ribbon-client/src/main/resources/application.yml b/spring-cloud/spring-cloud-ribbon-client/src/main/resources/application.yml new file mode 100644 index 0000000000..189a923c6c --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/src/main/resources/application.yml @@ -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 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppTests.java b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppTests.java new file mode 100644 index 0000000000..b3606537a2 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/ServerLocationAppTests.java @@ -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 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"); + } +} diff --git a/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/TestConfig.java b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/TestConfig.java new file mode 100644 index 0000000000..886b28a32e --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/spring/cloud/ribbon/client/TestConfig.java @@ -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"; + } +} diff --git a/spring-data-solr/pom.xml b/spring-data-solr/pom.xml new file mode 100644 index 0000000000..bd48a53d06 --- /dev/null +++ b/spring-data-solr/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + com.baeldung + spring-data-solr + 0.0.1-SNAPSHOT + jar + spring-data-solr + + + + UTF-8 + 4.2.5.RELEASE + 2.19.1 + 2.0.4.RELEASE + + + + + org.springframework + spring-core + ${spring.version} + + + org.springframework.data + spring-data-solr + ${spring-data-solr} + + + org.springframework + spring-context + ${spring.version} + + + log4j + log4j + 1.2.16 + + + junit + junit + 4.12 + test + + + org.springframework + spring-test + ${spring.version} + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + + + + + + + diff --git a/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java new file mode 100644 index 0000000000..1fe1e5468b --- /dev/null +++ b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/config/SolrConfig.java @@ -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); + } +} diff --git a/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/model/Product.java b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/model/Product.java new file mode 100644 index 0000000000..7cd0890718 --- /dev/null +++ b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/model/Product.java @@ -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; + } + +} diff --git a/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java new file mode 100644 index 0000000000..01ec1fb909 --- /dev/null +++ b/spring-data-solr/src/main/java/com/baeldung/spring/data/solr/repository/ProductRepository.java @@ -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 { + + public List findByName(String name); + + @Query("name:*?0* OR category:*?0* OR description:*?0*") + public Page findByCustomQuery(String searchTerm, Pageable pageable); + + @Query(name = "Product.findByNamedQuery") + public Page findByNamedQuery(String searchTerm, Pageable pageable); + +} diff --git a/spring-data-solr/src/main/resources/solr-named-queries.properties b/spring-data-solr/src/main/resources/solr-named-queries.properties new file mode 100644 index 0000000000..cec59cbebd --- /dev/null +++ b/spring-data-solr/src/main/resources/solr-named-queries.properties @@ -0,0 +1 @@ +Product.findByNamedQuery=name:*?0* OR category:*?0* OR description:*?0* \ No newline at end of file diff --git a/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryIntegrationTest.java b/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryIntegrationTest.java new file mode 100644 index 0000000000..74d94ef91c --- /dev/null +++ b/spring-data-solr/src/test/java/com/baeldung/spring/data/solr/repo/ProductRepositoryIntegrationTest.java @@ -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 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 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 result = productRepository.findByNamedQuery("one", new PageRequest(0, 10)); + assertEquals(3, result.getNumberOfElements()); + } + +} diff --git a/spring-dispatcher-servlet/src/main/resources/README.md b/spring-dispatcher-servlet/src/main/resources/README.md new file mode 100644 index 0000000000..7c97e75a2c --- /dev/null +++ b/spring-dispatcher-servlet/src/main/resources/README.md @@ -0,0 +1,3 @@ +## Info ## + +- The diagram is created with [yed](http://www.yworks.com/products/yed) diff --git a/spring-dispatcher-servlet/src/main/resources/diagram.graphml b/spring-dispatcher-servlet/src/main/resources/diagram.graphml new file mode 100644 index 0000000000..1806ab7719 --- /dev/null +++ b/spring-dispatcher-servlet/src/main/resources/diagram.graphml @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Servlet Engine (e.g. Tomcat) + + + + + + + + + + Folder 1 + + + + + + + + + + + + + + + + Controller + + + + + + + + + + + + + + + + + + + Model + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Model + + + + + + + + + + + + + + + + + + + + DispatcherServlet + + + + + + + + + + + + + + + + + + + View Template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Return Control + + + + + + + + + + + + Render Response + + + + + + + + + + + + Delegate Request + + + + + + + + + + + + Delegate Rendering of Response + + + + + + + + + + + + + + + + + + + + + + + + + Incoming Request + + + + + + + + + + + + Return Response + + + + + + + + + + + + + + Handle Request + + + + + + + + + + + + + + Create Model + + + + + + + + + <?xml version="1.0" encoding="utf-8"?> +<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"> +<g> + + <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"> + <stop offset="0" style="stop-color:#B38E5D"/> + <stop offset="1" style="stop-color:#805126"/> + </radialGradient> + <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"/> + + <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"> + <stop offset="0" style="stop-color:#B38E5D"/> + <stop offset="1" style="stop-color:#805126"/> + </radialGradient> + <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"/> + + <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"> + <stop offset="0" style="stop-color:#B38E5D"/> + <stop offset="1" style="stop-color:#805126"/> + </radialGradient> + <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"/> + + <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)"> + <stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.42"/> + <stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.12"/> + </linearGradient> + <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"/> + <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"/> + + <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"> + <stop offset="0" style="stop-color:#B0E8FF"/> + <stop offset="1" style="stop-color:#74AEEE"/> + </radialGradient> + <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"/> + + <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"> + <stop offset="0" style="stop-color:#80CCFF"/> + <stop offset="1" style="stop-color:#74AEEE"/> + </radialGradient> + <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 + "/> + + <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"> + <stop offset="0" style="stop-color:#80CCFF"/> + <stop offset="1" style="stop-color:#74AEEE"/> + </radialGradient> + <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"/> + + <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"> + <stop offset="0" style="stop-color:#80CCFF"/> + <stop offset="1" style="stop-color:#74AEEE"/> + </radialGradient> + <circle id="Knob2_1_" fill="url(#Knob2_2_)" stroke="#5491CF" cx="28.258" cy="56.254" r="0.584"/> + + <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"> + <stop offset="0" style="stop-color:#80CCFF"/> + <stop offset="1" style="stop-color:#74AEEE"/> + </radialGradient> + <circle id="Knob1_1_" fill="url(#Knob1_2_)" stroke="#5491CF" cx="28.296" cy="62.499" r="0.584"/> +</g> +</svg> + + + + diff --git a/spring-dispatcher-servlet/src/main/resources/diagram.png b/spring-dispatcher-servlet/src/main/resources/diagram.png new file mode 100644 index 0000000000..c0c545d680 Binary files /dev/null and b/spring-dispatcher-servlet/src/main/resources/diagram.png differ diff --git a/spring-mvc-email/README.md b/spring-mvc-email/README.md new file mode 100644 index 0000000000..0de6532393 --- /dev/null +++ b/spring-mvc-email/README.md @@ -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. \ No newline at end of file diff --git a/spring-mvc-email/pom.xml b/spring-mvc-email/pom.xml new file mode 100644 index 0000000000..0d3acec1fe --- /dev/null +++ b/spring-mvc-email/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + org.baeldung.spring + SpringMVCEmail + 1.0 + war + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-mail + 1.4.0.RELEASE + + + + org.apache.tomcat.embed + tomcat-embed-jasper + 8.5.4 + + + javax.servlet + jstl + 1.2 + + + + + 1.8 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/Application.java b/spring-mvc-email/src/main/java/com/baeldung/spring/Application.java new file mode 100644 index 0000000000..f146ee1d04 --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/Application.java @@ -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); + } +} diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/app/config/AppConfig.java b/spring-mvc-email/src/main/java/com/baeldung/spring/app/config/AppConfig.java new file mode 100644 index 0000000000..9078d44764 --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/app/config/AppConfig.java @@ -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 +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; + } +} diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/HomeController.java b/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/HomeController.java new file mode 100644 index 0000000000..656e237a9e --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/HomeController.java @@ -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"; + } +} diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/MailController.java b/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/MailController.java new file mode 100644 index 0000000000..768a0f8e7b --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/controllers/MailController.java @@ -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> labels; + + static { + labels = new HashMap<>(); + + //Simple email + Map 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:
" + + "This is the test email template for your email:
'Template Parameter'
" + ); + 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 props = labels.get(action); + Set keys = props.keySet(); + Iterator 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"; + } +} diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailService.java b/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailService.java new file mode 100644 index 0000000000..43d7378227 --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailService.java @@ -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); +} diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java b/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java new file mode 100644 index 0000000000..ca418a7d90 --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java @@ -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(); + } + } +} diff --git a/spring-mvc-email/src/main/java/com/baeldung/spring/web/dto/MailObject.java b/spring-mvc-email/src/main/java/com/baeldung/spring/web/dto/MailObject.java new file mode 100644 index 0000000000..9623ff5d78 --- /dev/null +++ b/spring-mvc-email/src/main/java/com/baeldung/spring/web/dto/MailObject.java @@ -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; + } +} diff --git a/spring-mvc-email/src/main/resources/META-INF/application.xml b/spring-mvc-email/src/main/resources/META-INF/application.xml new file mode 100644 index 0000000000..759a312bd4 --- /dev/null +++ b/spring-mvc-email/src/main/resources/META-INF/application.xml @@ -0,0 +1,19 @@ + + + + + + SpringMVCEmail.war + SpringMVCEmail + + + + + web.war + SpringMVCEmailWeb + + + \ No newline at end of file diff --git a/spring-mvc-email/src/main/resources/application.properties b/spring-mvc-email/src/main/resources/application.properties new file mode 100644 index 0000000000..61a42050e5 --- /dev/null +++ b/spring-mvc-email/src/main/resources/application.properties @@ -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 \ No newline at end of file diff --git a/spring-mvc-email/src/main/webapp/WEB-INF/views/home.jsp b/spring-mvc-email/src/main/webapp/WEB-INF/views/home.jsp new file mode 100644 index 0000000000..63351bbf3a --- /dev/null +++ b/spring-mvc-email/src/main/webapp/WEB-INF/views/home.jsp @@ -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" %> + + + Home Page + + +
+
+

Select any of the options below to send sample email:

+
+
+ + + + + + + + + + +
+ +
+ +
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/spring-mvc-email/src/main/webapp/WEB-INF/views/mail/send.jsp b/spring-mvc-email/src/main/webapp/WEB-INF/views/mail/send.jsp new file mode 100644 index 0000000000..d27aa09d9a --- /dev/null +++ b/spring-mvc-email/src/main/webapp/WEB-INF/views/mail/send.jsp @@ -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" %> + + + Send Email + + +
+

${headerText}

+ +
+
+ + + + + + + + + + + + + + + + + +
+ Enter email address
+ +
+ Enter the subject
+ +
+ +
+ +
+
+
+ ${additionalInfo} +
+
+
+
+ + diff --git a/spring-mvc-email/src/main/webapp/WEB-INF/web.xml b/spring-mvc-email/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..4cd41216d9 --- /dev/null +++ b/spring-mvc-email/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,29 @@ + + + + + simpleweb + org.springframework.web.servlet.DispatcherServlet + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + contextConfigLocation + com.baeldung.spring.app.config.AppConfig + + 1 + + + + simpleweb + / + + + diff --git a/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpFileUploadingLiveTest.java b/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpFileUploadingLiveTest.java index d1cc67b99a..2c88408017 100644 --- a/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpFileUploadingLiveTest.java +++ b/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpFileUploadingLiveTest.java @@ -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); diff --git a/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpGetLiveTest.java b/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpGetLiveTest.java index 9a49c8d9a2..3f773bf35e 100644 --- a/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpGetLiveTest.java +++ b/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpGetLiveTest.java @@ -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); } } diff --git a/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpMiscLiveTest.java b/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpMiscLiveTest.java index c44500f4be..9c38c8da51 100644 --- a/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpMiscLiveTest.java +++ b/spring-rest/src/test/java/org/baeldung/okhttp/OkHttpMiscLiveTest.java @@ -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 diff --git a/spring-session/jetty-session-demo/pom.xml b/spring-session/jetty-session-demo/pom.xml new file mode 100644 index 0000000000..86a8596862 --- /dev/null +++ b/spring-session/jetty-session-demo/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + com.baeldung + jetty-session-demo + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.session + spring-session + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.RELEASE + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/JettyWebApplication.java b/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/JettyWebApplication.java new file mode 100644 index 0000000000..7bbc776eaa --- /dev/null +++ b/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/JettyWebApplication.java @@ -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 ""; + } +} diff --git a/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SecurityConfig.java b/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SecurityConfig.java new file mode 100644 index 0000000000..6ed7df9218 --- /dev/null +++ b/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SecurityConfig.java @@ -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"); + } +} diff --git a/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SessionConfig.java b/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SessionConfig.java new file mode 100644 index 0000000000..f261f66f9d --- /dev/null +++ b/spring-session/jetty-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SessionConfig.java @@ -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(); + } +} diff --git a/spring-session/jetty-session-demo/src/main/resources/application.properties b/spring-session/jetty-session-demo/src/main/resources/application.properties new file mode 100644 index 0000000000..7f81672eda --- /dev/null +++ b/spring-session/jetty-session-demo/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port=8081 +spring.redis.host=localhost +spring.redis.port=6379 \ No newline at end of file diff --git a/spring-session/pom.xml b/spring-session/pom.xml new file mode 100644 index 0000000000..fec6a46af2 --- /dev/null +++ b/spring-session/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + spring-session + 1.0.0-SNAPSHOT + pom + + + jetty-session-demo + tomcat-session-demo + + \ No newline at end of file diff --git a/spring-session/tomcat-session-demo/pom.xml b/spring-session/tomcat-session-demo/pom.xml new file mode 100644 index 0000000000..805d7bec25 --- /dev/null +++ b/spring-session/tomcat-session-demo/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.baeldung + tomcat-session-demo + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.session + spring-session + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.RELEASE + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SecurityConfig.java b/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SecurityConfig.java new file mode 100644 index 0000000000..3e419b27a2 --- /dev/null +++ b/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SecurityConfig.java @@ -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(); + } +} diff --git a/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SessionConfig.java b/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SessionConfig.java new file mode 100644 index 0000000000..5afac6cb6b --- /dev/null +++ b/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/SessionConfig.java @@ -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 { +} diff --git a/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/TomcatWebApplication.java b/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/TomcatWebApplication.java new file mode 100644 index 0000000000..58c6b807ec --- /dev/null +++ b/spring-session/tomcat-session-demo/src/main/java/com/baeldung/spring/session/tomcatex/TomcatWebApplication.java @@ -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"; + } +} diff --git a/spring-session/tomcat-session-demo/src/main/resources/application.properties b/spring-session/tomcat-session-demo/src/main/resources/application.properties new file mode 100644 index 0000000000..49886b3b70 --- /dev/null +++ b/spring-session/tomcat-session-demo/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.redis.host=localhost +spring.redis.port=6379 \ No newline at end of file diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml new file mode 100644 index 0000000000..6e74b1c3d1 --- /dev/null +++ b/spring-social-login/pom.xml @@ -0,0 +1,169 @@ + + 4.0.0 + spring-social-login + + spring-social-login + war + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + org.springframework.security + spring-security-web + + + + org.springframework.security + spring-security-config + + + + org.springframework.security + spring-security-taglibs + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + + org.springframework.social + spring-social-facebook + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework + spring-test + test + + + + junit + junit + test + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + + spring-social-login + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + + + **/*IntegrationTest.java + + + + + + + json + + + + + + + + + + 1.8 + 3.3.2 + + + \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/config/Application.java b/spring-social-login/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..cf6251a51e --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/config/Application.java @@ -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); + } + +} \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..8e439653a9 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/config/SecurityConfig.java @@ -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()); + } +} \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/config/WebConfig.java b/spring-social-login/src/main/java/org/baeldung/config/WebConfig.java new file mode 100644 index 0000000000..8cfcd6cb41 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/config/WebConfig.java @@ -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/"); + } + +} \ No newline at end of file diff --git a/spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java new file mode 100644 index 0000000000..679dd6c363 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/persistence/dao/UserRepository.java @@ -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 findByUsername(final String username); + +} diff --git a/spring-social-login/src/main/java/org/baeldung/persistence/model/User.java b/spring-social-login/src/main/java/org/baeldung/persistence/model/User.java new file mode 100644 index 0000000000..a4cffc27d0 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/persistence/model/User.java @@ -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(); + } + +} diff --git a/spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java b/spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java new file mode 100644 index 0000000000..6a9e30d7d8 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/security/FacebookConnectionSignup.java @@ -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(); + } + +} diff --git a/spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java b/spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java new file mode 100644 index 0000000000..b861609a01 --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/security/FacebookSignInAdapter.java @@ -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; + } +} diff --git a/spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java new file mode 100644 index 0000000000..5d0d5d793a --- /dev/null +++ b/spring-social-login/src/main/java/org/baeldung/security/MyUserDetailsService.java @@ -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"))); + } +} diff --git a/spring-social-login/src/main/resources/application.properties b/spring-social-login/src/main/resources/application.properties new file mode 100644 index 0000000000..2bd99d8239 --- /dev/null +++ b/spring-social-login/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.social.facebook.appId=1715784745414888 +spring.social.facebook.appSecret=abefd6497e9cc01ad03be28509617bf0 +spring.thymeleaf.cache=false \ No newline at end of file diff --git a/spring-social-login/src/main/resources/data.sql b/spring-social-login/src/main/resources/data.sql new file mode 100644 index 0000000000..3b26afef32 --- /dev/null +++ b/spring-social-login/src/main/resources/data.sql @@ -0,0 +1 @@ +insert into User (id, username, password) values (1,'john', '123'); \ No newline at end of file diff --git a/spring-social-login/src/main/resources/templates/index.html b/spring-social-login/src/main/resources/templates/index.html new file mode 100644 index 0000000000..8e1a8da60f --- /dev/null +++ b/spring-social-login/src/main/resources/templates/index.html @@ -0,0 +1,27 @@ + + + + +Spring Social Login + + + + + + +
+

Welcome, Username

+

User authorities

+
+ + \ No newline at end of file diff --git a/spring-social-login/src/main/resources/templates/login.html b/spring-social-login/src/main/resources/templates/login.html new file mode 100644 index 0000000000..41ad39332c --- /dev/null +++ b/spring-social-login/src/main/resources/templates/login.html @@ -0,0 +1,44 @@ + + + + +Spring Social Login + + + +
+
You have been logged out
+
There was an error, please try again
+ +

Login

+
+
+
+ + +
+
+
+ + +
+ +
+ +
+
+
+
+
+
+
+
+ + +
+
+ + +
+ + \ No newline at end of file diff --git a/spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java b/spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java new file mode 100644 index 0000000000..43aaea18b1 --- /dev/null +++ b/spring-social-login/src/test/java/org/baeldung/test/ApplicationIntegrationTest.java @@ -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() { + + } +}