diff --git a/JGit/README.md b/JGit/README.md new file mode 100644 index 0000000000..5c65f1101b --- /dev/null +++ b/JGit/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [A Guide to JGit](http://www.baeldung.com/jgit) diff --git a/Twitter4J/pom.xml b/Twitter4J/pom.xml new file mode 100644 index 0000000000..ebe5a7d409 --- /dev/null +++ b/Twitter4J/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + com.mabsisa + Twitter4J + jar + 1.0-SNAPSHOT + Twitter4J + http://maven.apache.org + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + org.twitter4j + twitter4j-core + 4.0.6 + + + org.twitter4j + twitter4j-stream + 4.0.6 + + + junit + junit + 4.12 + + + + + ${project.artifactId} + + + src/main/resources + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + **/ApplicationTest.java + + + + + + + diff --git a/Twitter4J/src/main/java/com/baeldung/Application.java b/Twitter4J/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..f7da27db29 --- /dev/null +++ b/Twitter4J/src/main/java/com/baeldung/Application.java @@ -0,0 +1,117 @@ +/** + * + */ +package com.baeldung; + +import java.util.List; +import java.util.stream.Collectors; + +import twitter4j.DirectMessage; +import twitter4j.Query; +import twitter4j.QueryResult; +import twitter4j.StallWarning; +import twitter4j.Status; +import twitter4j.StatusDeletionNotice; +import twitter4j.StatusListener; +import twitter4j.Twitter; +import twitter4j.TwitterException; +import twitter4j.TwitterFactory; +import twitter4j.TwitterStream; +import twitter4j.TwitterStreamFactory; +import twitter4j.conf.ConfigurationBuilder; + +public class Application { + + public static Twitter getTwitterinstance() { + /** + * if not using properties file, we can set access token by following way + */ +// ConfigurationBuilder cb = new ConfigurationBuilder(); +// cb.setDebugEnabled(true) +// .setOAuthConsumerKey("DPHTBsWWO42d8rzshxlK0OwSY") +// .setOAuthConsumerSecret("ACLXkeRY98NiaVCG1ai8fdYt0GoEGJbFeTuxjulSCO7sLKqls1") +// .setOAuthAccessToken("838080188214759428-9MSK1ddPTN5ZZHbddjFI7s75mYgmCFQ") +// .setOAuthAccessTokenSecret("1eXAADpHShAzQh5hGWLBUQHLysOuAKIOapmQQ8U0OVk2c"); +// +// TwitterFactory tf = new TwitterFactory(cb.build()); +// Twitter twitter = tf.getSingleton(); + + Twitter twitter = TwitterFactory.getSingleton(); + return twitter; + + } + + public static String createTweet(String tweet) throws TwitterException { + Twitter twitter = getTwitterinstance(); + Status status = twitter.updateStatus("creating baeldung API"); + return status.getText(); + } + + public static List getTimeLine() throws TwitterException { + Twitter twitter = getTwitterinstance(); + List statuses = twitter.getHomeTimeline(); + return statuses.stream().map( + item -> item.getText()).collect( + Collectors.toList()); + } + + public static String sendDirectMessage(String recipientName, String msg) throws TwitterException { + Twitter twitter = getTwitterinstance(); + DirectMessage message = twitter.sendDirectMessage(recipientName, msg); + return message.getText(); + } + + public static List searchtweets() throws TwitterException { + Twitter twitter = getTwitterinstance(); + Query query = new Query("source:twitter4j baeldung"); + QueryResult result = twitter.search(query); + List statuses = result.getTweets(); + return statuses.stream().map( + item -> item.getText()).collect( + Collectors.toList()); + } + + public static void streamFeed() { + + StatusListener listener = new StatusListener(){ + + @Override + public void onException(Exception e) { + e.printStackTrace(); + } + + @Override + public void onDeletionNotice(StatusDeletionNotice arg) { + System.out.println("Got a status deletion notice id:" + arg.getStatusId()); + } + + @Override + public void onScrubGeo(long userId, long upToStatusId) { + System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId); + } + + @Override + public void onStallWarning(StallWarning warning) { + System.out.println("Got stall warning:" + warning); + } + + @Override + public void onStatus(Status status) { + System.out.println(status.getUser().getName() + " : " + status.getText()); + } + + @Override + public void onTrackLimitationNotice(int numberOfLimitedStatuses) { + System.out.println("Got track limitation notice:" + numberOfLimitedStatuses); + } + }; + + TwitterStream twitterStream = new TwitterStreamFactory().getInstance(); + + twitterStream.addListener(listener); + + twitterStream.sample(); + + } + +} diff --git a/Twitter4J/src/main/resources/twitter4j.properties b/Twitter4J/src/main/resources/twitter4j.properties new file mode 100644 index 0000000000..ee11dc62a1 --- /dev/null +++ b/Twitter4J/src/main/resources/twitter4j.properties @@ -0,0 +1,4 @@ +oauth.consumerKey=//TODO +oauth.consumerSecret=//TODO +oauth.accessToken=//TODO +oauth.accessTokenSecret=//TODO diff --git a/Twitter4J/src/test/java/com/baeldung/ApplicationTest.java b/Twitter4J/src/test/java/com/baeldung/ApplicationTest.java new file mode 100644 index 0000000000..a1c778679c --- /dev/null +++ b/Twitter4J/src/test/java/com/baeldung/ApplicationTest.java @@ -0,0 +1,40 @@ +package com.baeldung; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import twitter4j.TwitterException; + +public class ApplicationTest { + + /** + * In order run this jUnit test you need to configure your API details in the twitter4j.properties + */ + + String tweet = "baeldung is awsome"; + + @Test + public void givenText_updateStatus() throws TwitterException { + String text = Application.createTweet(tweet); + assertEquals(tweet, text); + } + + @Test + public void givenCredential_fetchStatus() throws TwitterException { + List statuses = Application.getTimeLine(); + List expectedStatuses = new ArrayList(); + expectedStatuses.add(tweet); + assertEquals(expectedStatuses, statuses); + } + + @Test + public void givenRecipientNameAndMessage_sendDirectMessage() throws TwitterException { + String msg = Application.sendDirectMessage("YOUR_RECCIPIENT_ID", tweet); + assertEquals(msg, tweet); + } + +} diff --git a/algorithms/README.md b/algorithms/README.md new file mode 100644 index 0000000000..42f696d9be --- /dev/null +++ b/algorithms/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Dijkstra Algorithm in Java](http://www.baeldung.com/java-dijkstra) +- [Introduction to Cobertura](http://www.baeldung.com/cobertura) diff --git a/algorithms/pom.xml b/algorithms/pom.xml index 0c85a19534..f72457650a 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -41,4 +41,23 @@ - \ No newline at end of file + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + + com/baeldung/algorithms/dijkstra/* + + + com/baeldung/algorithms/dijkstra/* + + + + + + + diff --git a/apache-bval/README.md b/apache-bval/README.md new file mode 100644 index 0000000000..80ea149993 --- /dev/null +++ b/apache-bval/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Intro to Apache BVal](http://www.baeldung.com/apache-bval) diff --git a/apache-commons/pom.xml b/apache-commons/pom.xml new file mode 100644 index 0000000000..6e5c2065db --- /dev/null +++ b/apache-commons/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + com.baeldung + apache-commons + 0.0.1-SNAPSHOT + + 4.12 + 3.6.0 + + + + + maven-compiler-plugin + ${compiler.version} + + 1.8 + 1.8 + + + + + + + org.apache.commons + commons-lang3 + 3.5 + + + junit + junit + ${junit.version} + test + + + \ No newline at end of file diff --git a/apache-commons/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java b/apache-commons/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java new file mode 100644 index 0000000000..b579458730 --- /dev/null +++ b/apache-commons/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java @@ -0,0 +1,137 @@ +package com.baeldung.commons.lang3; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; + +public class ArrayUtilsTest { + @Test + public void givenArray_whenAddingElementAtSpecifiedPosition_thenCorrect() { + int[] oldArray = { 2, 3, 4, 5 }; + int[] newArray = ArrayUtils.add(oldArray, 0, 1); + int[] expectedArray = { 1, 2, 3, 4, 5 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenAddingElementAtTheEnd_thenCorrect() { + int[] oldArray = { 2, 3, 4, 5 }; + int[] newArray = ArrayUtils.add(oldArray, 1); + int[] expectedArray = { 2, 3, 4, 5, 1 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenAddingAllElementsAtTheEnd_thenCorrect() { + int[] oldArray = { 0, 1, 2 }; + int[] newArray = ArrayUtils.addAll(oldArray, 3, 4, 5); + int[] expectedArray = { 0, 1, 2, 3, 4, 5 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenRemovingElementAtSpecifiedPosition_thenCorrect() { + int[] oldArray = { 1, 2, 3, 4, 5 }; + int[] newArray = ArrayUtils.remove(oldArray, 1); + int[] expectedArray = { 1, 3, 4, 5 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenRemovingAllElementsAtSpecifiedPositions_thenCorrect() { + int[] oldArray = { 1, 2, 3, 4, 5 }; + int[] newArray = ArrayUtils.removeAll(oldArray, 1, 3); + int[] expectedArray = { 1, 3, 5 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenRemovingAnElement_thenCorrect() { + int[] oldArray = { 1, 2, 3, 3, 4 }; + int[] newArray = ArrayUtils.removeElement(oldArray, 3); + int[] expectedArray = { 1, 2, 3, 4 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenRemovingElements_thenCorrect() { + int[] oldArray = { 1, 2, 3, 3, 4 }; + int[] newArray = ArrayUtils.removeElements(oldArray, 2, 3, 5); + int[] expectedArray = { 1, 3, 4 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenRemovingAllElementOccurences_thenCorrect() { + int[] oldArray = { 1, 2, 2, 2, 3 }; + int[] newArray = ArrayUtils.removeAllOccurences(oldArray, 2); + int[] expectedArray = { 1, 3 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenCheckingExistingElement_thenCorrect() { + int[] array = { 1, 3, 5, 7, 9 }; + boolean evenContained = ArrayUtils.contains(array, 2); + boolean oddContained = ArrayUtils.contains(array, 7); + assertEquals(false, evenContained); + assertEquals(true, oddContained); + } + + @Test + public void givenArray_whenReversingElementsWithinARange_thenCorrect() { + int[] originalArray = { 1, 2, 3, 4, 5 }; + ArrayUtils.reverse(originalArray, 1, 4); + int[] expectedArray = { 1, 4, 3, 2, 5 }; + assertArrayEquals(expectedArray, originalArray); + } + + @Test + public void givenArray_whenReversingAllElements_thenCorrect() { + int[] originalArray = { 1, 2, 3, 4, 5 }; + ArrayUtils.reverse(originalArray); + int[] expectedArray = { 5, 4, 3, 2, 1 }; + assertArrayEquals(expectedArray, originalArray); + } + + @Test + public void givenArray_whenShiftingElementsWithinARange_thenCorrect() { + int[] originalArray = { 1, 2, 3, 4, 5 }; + ArrayUtils.shift(originalArray, 1, 4, 1); + int[] expectedArray = { 1, 4, 2, 3, 5 }; + assertArrayEquals(expectedArray, originalArray); + } + + @Test + public void givenArray_whenShiftingAllElements_thenCorrect() { + int[] originalArray = { 1, 2, 3, 4, 5 }; + ArrayUtils.shift(originalArray, 1); + int[] expectedArray = { 5, 1, 2, 3, 4 }; + assertArrayEquals(expectedArray, originalArray); + } + + @Test + public void givenArray_whenExtractingElements_thenCorrect() { + int[] oldArray = { 1, 2, 3, 4, 5 }; + int[] newArray = ArrayUtils.subarray(oldArray, 2, 7); + int[] expectedArray = { 3, 4, 5 }; + assertArrayEquals(expectedArray, newArray); + } + + @Test + public void givenArray_whenSwapingElementsWithinARange_thenCorrect() { + int[] originalArray = { 1, 2, 3, 4, 5 }; + ArrayUtils.swap(originalArray, 0, 3, 2); + int[] expectedArray = { 4, 5, 3, 1, 2 }; + assertArrayEquals(expectedArray, originalArray); + } + + @Test + public void givenArray_whenSwapingElementsAtSpecifiedPositions_thenCorrect() { + int[] originalArray = { 1, 2, 3, 4, 5 }; + ArrayUtils.swap(originalArray, 0, 3); + int[] expectedArray = { 4, 2, 3, 1, 5 }; + assertArrayEquals(expectedArray, originalArray); + } +} diff --git a/apache-commons/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java b/apache-commons/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java new file mode 100644 index 0000000000..a17a8ea60d --- /dev/null +++ b/apache-commons/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java @@ -0,0 +1,99 @@ +package com.baeldung.commons.lang3; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +public class StringUtilsTest { + @Test + public void givenString_whenCheckingContainsAny_thenCorrect() { + String string = "baeldung.com"; + boolean contained1 = StringUtils.containsAny(string, 'a', 'b', 'c'); + boolean contained2 = StringUtils.containsAny(string, 'x', 'y', 'z'); + boolean contained3 = StringUtils.containsAny(string, "abc"); + boolean contained4 = StringUtils.containsAny(string, "xyz"); + assertTrue(contained1); + assertFalse(contained2); + assertTrue(contained3); + assertFalse(contained4); + } + + @Test + public void givenString_whenCheckingContainsIgnoreCase_thenCorrect() { + String string = "baeldung.com"; + boolean contained = StringUtils.containsIgnoreCase(string, "BAELDUNG"); + assertTrue(contained); + } + + @Test + public void givenString_whenCountingMatches_thenCorrect() { + String string = "welcome to www.baeldung.com"; + int charNum = StringUtils.countMatches(string, 'w'); + int stringNum = StringUtils.countMatches(string, "com"); + assertEquals(4, charNum); + assertEquals(2, stringNum); + } + + @Test + public void givenString_whenAppendingAndPrependingIfMissing_thenCorrect() { + String string = "baeldung.com"; + String stringWithSuffix = StringUtils.appendIfMissing(string, ".com"); + String stringWithPrefix = StringUtils.prependIfMissing(string, "www."); + assertEquals("baeldung.com", stringWithSuffix); + assertEquals("www.baeldung.com", stringWithPrefix); + } + + @Test + public void givenString_whenSwappingCase_thenCorrect() { + String originalString = "baeldung.COM"; + String swappedString = StringUtils.swapCase(originalString); + assertEquals("BAELDUNG.com", swappedString); + } + + @Test + public void givenString_whenCapitalizing_thenCorrect() { + String originalString = "baeldung"; + String capitalizedString = StringUtils.capitalize(originalString); + assertEquals("Baeldung", capitalizedString); + } + + @Test + public void givenString_whenUncapitalizing_thenCorrect() { + String originalString = "Baeldung"; + String uncapitalizedString = StringUtils.uncapitalize(originalString); + assertEquals("baeldung", uncapitalizedString); + } + + @Test + public void givenString_whenReversingCharacters_thenCorrect() { + String originalString = "baeldung"; + String reversedString = StringUtils.reverse(originalString); + assertEquals("gnudleab", reversedString); + } + + @Test + public void givenString_whenReversingWithDelimiter_thenCorrect() { + String originalString = "www.baeldung.com"; + String reversedString = StringUtils.reverseDelimited(originalString, '.'); + assertEquals("com.baeldung.www", reversedString); + } + + @Test + public void givenString_whenRotatingTwoPositions_thenCorrect() { + String originalString = "baeldung"; + String rotatedString = StringUtils.rotate(originalString, 4); + assertEquals("dungbael", rotatedString); + } + + @Test + public void givenTwoStrings_whenComparing_thenCorrect() { + String tutorials = "Baeldung Tutorials"; + String courses = "Baeldung Courses"; + String diff1 = StringUtils.difference(tutorials, courses); + String diff2 = StringUtils.difference(courses, tutorials); + assertEquals("Courses", diff1); + assertEquals("Tutorials", diff2); + } +} diff --git a/apache-solrj/README.md b/apache-solrj/README.md new file mode 100644 index 0000000000..7a32becb64 --- /dev/null +++ b/apache-solrj/README.md @@ -0,0 +1,4 @@ +## Apache Solrj Tutorials Project + +### Relevant Articles +- [Guide to Solr in Java with Apache Solrj](http://www.baeldung.com/apache-solrj) diff --git a/apache-solrj/pom.xml b/apache-solrj/pom.xml new file mode 100644 index 0000000000..74daeae55c --- /dev/null +++ b/apache-solrj/pom.xml @@ -0,0 +1,50 @@ + + 4.0.0 + com.baeldung + apache-solrj + 0.0.1-SNAPSHOT + jar + apache-solrj + + + 4.12 + 2.19.1 + + + + + org.apache.solr + solr-solrj + 6.4.0 + + + junit + junit + ${junit.version} + test + + + + + + + maven-compiler-plugin + 2.3.2 + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 1.8 + 1.8 + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + \ No newline at end of file diff --git a/apache-solrj/src/main/java/com/baeldung/solrjava/ProductBean.java b/apache-solrj/src/main/java/com/baeldung/solrjava/ProductBean.java new file mode 100644 index 0000000000..14eea8f2f9 --- /dev/null +++ b/apache-solrj/src/main/java/com/baeldung/solrjava/ProductBean.java @@ -0,0 +1,44 @@ +package com.baeldung.solrjava; + +import org.apache.solr.client.solrj.beans.Field; + +public class ProductBean { + + String id; + String name; + String price; + + public ProductBean(String id, String name, String price) { + super(); + this.id = id; + this.name = name; + this.price = price; + } + + public String getId() { + return id; + } + + @Field("id") + protected void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + @Field("name") + protected void setName(String name) { + this.name = name; + } + + public String getPrice() { + return price; + } + + @Field("price") + protected void setPrice(String price) { + this.price = price; + } +} diff --git a/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java b/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java new file mode 100644 index 0000000000..c55e1c9ada --- /dev/null +++ b/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java @@ -0,0 +1,56 @@ +package com.baeldung.solrjava; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.impl.XMLResponseParser; +import org.apache.solr.common.SolrInputDocument; + +public class SolrJavaIntegration { + + private HttpSolrClient solrClient; + + public SolrJavaIntegration(String clientUrl) { + + solrClient = new HttpSolrClient.Builder(clientUrl).build(); + solrClient.setParser(new XMLResponseParser()); + } + + public void addProductBean(ProductBean pBean) throws IOException, SolrServerException { + + solrClient.addBean(pBean); + solrClient.commit(); + } + + public void addSolrDocument(String documentId, String itemName, String itemPrice) throws SolrServerException, IOException { + + SolrInputDocument document = new SolrInputDocument(); + document.addField("id", documentId); + document.addField("name", itemName); + document.addField("price", itemPrice); + solrClient.add(document); + solrClient.commit(); + } + + public void deleteSolrDocumentById(String documentId) throws SolrServerException, IOException { + + solrClient.deleteById(documentId); + solrClient.commit(); + } + + public void deleteSolrDocumentByQuery(String query) throws SolrServerException, IOException { + + solrClient.deleteByQuery(query); + solrClient.commit(); + } + + protected HttpSolrClient getSolrClient() { + return solrClient; + } + + protected void setSolrClient(HttpSolrClient solrClient) { + this.solrClient = solrClient; + } + +} diff --git a/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java new file mode 100644 index 0000000000..8b5fe77c6f --- /dev/null +++ b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java @@ -0,0 +1,108 @@ +package com.baeldung.solrjava; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrDocumentList; +import org.junit.Before; +import org.junit.Test; + +public class SolrJavaIntegrationTest { + + private SolrJavaIntegration solrJavaIntegration; + + @Before + public void setUp() throws Exception { + + solrJavaIntegration = new SolrJavaIntegration("http://localhost:8983/solr/bigboxstore"); + solrJavaIntegration.addSolrDocument("123456", "Kenmore Dishwasher", "599.99"); + } + + @Test + public void whenAdd_thenVerifyAddedByQueryOnId() throws SolrServerException, IOException { + + SolrQuery query = new SolrQuery(); + query.set("q", "id:123456"); + QueryResponse response = null; + + response = solrJavaIntegration.getSolrClient().query(query); + + SolrDocumentList docList = response.getResults(); + assertEquals(1, docList.getNumFound()); + + for (SolrDocument doc : docList) { + assertEquals("Kenmore Dishwasher", (String) doc.getFieldValue("name")); + assertEquals((Double) 599.99, (Double) doc.getFieldValue("price")); + } + } + + @Test + public void whenAdd_thenVerifyAddedByQueryOnPrice() throws SolrServerException, IOException { + + SolrQuery query = new SolrQuery(); + query.set("q", "price:599.99"); + QueryResponse response = null; + + response = solrJavaIntegration.getSolrClient().query(query); + + SolrDocumentList docList = response.getResults(); + assertEquals(1, docList.getNumFound()); + + for (SolrDocument doc : docList) { + assertEquals("123456", (String) doc.getFieldValue("id")); + assertEquals((Double) 599.99, (Double) doc.getFieldValue("price")); + } + } + + @Test + public void whenAdd_thenVerifyAddedByQuery() throws SolrServerException, IOException { + + SolrDocument doc = solrJavaIntegration.getSolrClient().getById("123456"); + assertEquals("Kenmore Dishwasher", (String) doc.getFieldValue("name")); + assertEquals((Double) 599.99, (Double) doc.getFieldValue("price")); + } + + @Test + public void whenAddBean_thenVerifyAddedByQuery() throws SolrServerException, IOException { + + ProductBean pBean = new ProductBean("888", "Apple iPhone 6s", "299.99"); + solrJavaIntegration.addProductBean(pBean); + + SolrDocument doc = solrJavaIntegration.getSolrClient().getById("888"); + assertEquals("Apple iPhone 6s", (String) doc.getFieldValue("name")); + assertEquals((Double) 299.99, (Double) doc.getFieldValue("price")); + } + + @Test + public void whenDeleteById_thenVerifyDeleted() throws SolrServerException, IOException { + + solrJavaIntegration.deleteSolrDocumentById("123456"); + + SolrQuery query = new SolrQuery(); + query.set("q", "id:123456"); + QueryResponse response = solrJavaIntegration.getSolrClient().query(query); + + SolrDocumentList docList = response.getResults(); + assertEquals(0, docList.getNumFound()); + } + + @Test + public void whenDeleteByQuery_thenVerifyDeleted() throws SolrServerException, IOException { + + solrJavaIntegration.deleteSolrDocumentByQuery("name:Kenmore Dishwasher"); + + SolrQuery query = new SolrQuery(); + query.set("q", "id:123456"); + QueryResponse response = null; + + response = solrJavaIntegration.getSolrClient().query(query); + + SolrDocumentList docList = response.getResults(); + assertEquals(0, docList.getNumFound()); + } +} diff --git a/apache-thrift/README.md b/apache-thrift/README.md new file mode 100644 index 0000000000..d8b9195dcc --- /dev/null +++ b/apache-thrift/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Working with Apache Thrift](http://www.baeldung.com/apache-thrift) diff --git a/apache-velocity/README.md b/apache-velocity/README.md new file mode 100644 index 0000000000..53c67f847e --- /dev/null +++ b/apache-velocity/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to Apache Velocity](http://www.baeldung.com/apache-velocity) diff --git a/aws/pom.xml b/aws/pom.xml index f3ae672a2f..681b76cfd4 100644 --- a/aws/pom.xml +++ b/aws/pom.xml @@ -7,17 +7,36 @@ jar aws + + 2.5 + 1.3.0 + 1.1.0 + 2.8.0 + + com.amazonaws aws-lambda-java-core - 1.1.0 + ${aws-lambda-java-core.version} + + + + com.amazonaws + aws-lambda-java-events + ${aws-lambda-java-events.version} commons-io commons-io - 2.5 + ${commons-io.version} + + + + com.google.code.gson + gson + ${gson.version} @@ -26,7 +45,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.3 + 3.0.0 false diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java new file mode 100644 index 0000000000..625da62efd --- /dev/null +++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java @@ -0,0 +1,49 @@ +package com.baeldung.lambda.dynamodb; + +import com.amazonaws.regions.Region; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; +import com.amazonaws.services.dynamodbv2.document.DynamoDB; +import com.amazonaws.services.dynamodbv2.document.Item; +import com.amazonaws.services.dynamodbv2.document.PutItemOutcome; +import com.amazonaws.services.dynamodbv2.document.spec.PutItemSpec; +import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.baeldung.lambda.dynamodb.bean.PersonRequest; +import com.baeldung.lambda.dynamodb.bean.PersonResponse; + +public class SavePersonHandler implements RequestHandler { + + private DynamoDB dynamoDb; + + private String DYNAMODB_TABLE_NAME = "Person"; + private Regions REGION = Regions.US_WEST_2; + + public PersonResponse handleRequest(PersonRequest personRequest, Context context) { + this.initDynamoDbClient(); + + persistData(personRequest); + + PersonResponse personResponse = new PersonResponse(); + personResponse.setMessage("Saved Successfully!!!"); + return personResponse; + } + + private PutItemOutcome persistData(PersonRequest personRequest) throws ConditionalCheckFailedException { + return this.dynamoDb.getTable(DYNAMODB_TABLE_NAME) + .putItem( + new PutItemSpec().withItem(new Item() + .withNumber("id", personRequest.getId()) + .withString("firstName", personRequest.getFirstName()) + .withString("lastName", personRequest.getLastName()) + .withNumber("age", personRequest.getAge()) + .withString("address", personRequest.getAddress()))); + } + + private void initDynamoDbClient() { + AmazonDynamoDBClient client = new AmazonDynamoDBClient(); + client.setRegion(Region.getRegion(REGION)); + this.dynamoDb = new DynamoDB(client); + } +} diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java new file mode 100644 index 0000000000..0c0706e676 --- /dev/null +++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java @@ -0,0 +1,67 @@ +package com.baeldung.lambda.dynamodb.bean; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class PersonRequest { + private int id; + private String firstName; + private String lastName; + private int age; + private String address; + + public static void main(String[] args) { + PersonRequest personRequest = new PersonRequest(); + personRequest.setId(1); + personRequest.setFirstName("John"); + personRequest.setLastName("Doe"); + personRequest.setAge(30); + personRequest.setAddress("United States"); + System.out.println(personRequest); + } + + public String toString() { + final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + return gson.toJson(this); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } +} diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java new file mode 100644 index 0000000000..a61294ddea --- /dev/null +++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java @@ -0,0 +1,20 @@ +package com.baeldung.lambda.dynamodb.bean; + +import com.google.gson.Gson; + +public class PersonResponse { + private String message; + + public String toString() { + final Gson gson = new Gson(); + return gson.toJson(this); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/core-java-9/README.md b/core-java-9/README.md index 1b44239e40..53ad79e59c 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -6,3 +6,5 @@ ### Relevant Articles: - [Java 9 Stream API Improvements](http://www.baeldung.com/java-9-stream-api) +- [Java 9 Convenience Factory Methods for Collections](http://www.baeldung.com/java-9-collections-factory-methods) +- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) diff --git a/core-java-9/pom.xml b/core-java-9/pom.xml index 9d1ff29ef7..23473ff161 100644 --- a/core-java-9/pom.xml +++ b/core-java-9/pom.xml @@ -21,6 +21,11 @@ slf4j-api ${org.slf4j.version} + + ch.qos.logback + logback-classic + ${ch.qos.logback.version} + org.hamcrest @@ -76,9 +81,9 @@ 1.7.21 - + 1.2.1 - 3.6-jigsaw-SNAPSHOT + 3.6.0 2.19.1 diff --git a/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java b/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java index 121c17a860..a6060b1a9d 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java +++ b/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java @@ -1,4 +1,4 @@ -package com.baeldung.java8; +package com.baeldung.java9; import static org.junit.Assert.assertEquals; @@ -8,7 +8,6 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.Before; import org.junit.Test; public class Java9OptionalsStreamTest { diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java new file mode 100644 index 0000000000..1129a10d17 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java @@ -0,0 +1,133 @@ +package com.baeldung.java9.process; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by sanaulla on 2/23/2017. + */ + +public class ProcessAPIEnhancementsTest { + + Logger log = LoggerFactory.getLogger(ProcessAPIEnhancementsTest.class); + + @Test + public void givenCurrentProcess_whenInvokeGetInfo_thenSuccess() throws IOException { + ProcessHandle processHandle = ProcessHandle.current(); + ProcessHandle.Info processInfo = processHandle.info(); + assertNotNull(processHandle.getPid()); + assertEquals(false, processInfo.arguments() + .isPresent()); + assertEquals(true, processInfo.command() + .isPresent()); + assertTrue(processInfo.command() + .get() + .contains("java")); + + assertEquals(true, processInfo.startInstant() + .isPresent()); + assertEquals(true, processInfo.totalCpuDuration() + .isPresent()); + assertEquals(true, processInfo.user() + .isPresent()); + } + + @Test + public void givenSpawnProcess_whenInvokeGetInfo_thenSuccess() throws IOException { + + String javaCmd = ProcessUtils.getJavaCmd() + .getAbsolutePath(); + ProcessBuilder processBuilder = new ProcessBuilder(javaCmd, "-version"); + Process process = processBuilder.inheritIO() + .start(); + ProcessHandle processHandle = process.toHandle(); + ProcessHandle.Info processInfo = processHandle.info(); + assertNotNull(processHandle.getPid()); + assertEquals(false, processInfo.arguments() + .isPresent()); + assertEquals(true, processInfo.command() + .isPresent()); + assertTrue(processInfo.command() + .get() + .contains("java")); + assertEquals(true, processInfo.startInstant() + .isPresent()); + assertEquals(true, processInfo.totalCpuDuration() + .isPresent()); + assertEquals(true, processInfo.user() + .isPresent()); + } + + @Test + public void givenLiveProcesses_whenInvokeGetInfo_thenSuccess() { + Stream liveProcesses = ProcessHandle.allProcesses(); + liveProcesses.filter(ProcessHandle::isAlive) + .forEach(ph -> { + assertNotNull(ph.getPid()); + assertEquals(true, ph.info() + .command() + .isPresent()); + assertEquals(true, ph.info() + .startInstant() + .isPresent()); + assertEquals(true, ph.info() + .totalCpuDuration() + .isPresent()); + assertEquals(true, ph.info() + .user() + .isPresent()); + }); + } + + @Test + public void givenProcess_whenGetChildProcess_thenSuccess() throws IOException { + int childProcessCount = 5; + for (int i = 0; i < childProcessCount; i++) { + String javaCmd = ProcessUtils.getJavaCmd() + .getAbsolutePath(); + ProcessBuilder processBuilder + = new ProcessBuilder(javaCmd, "-version"); + processBuilder.inheritIO().start(); + } + + Stream children = ProcessHandle.current() + .children(); + children.filter(ProcessHandle::isAlive) + .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info() + .command())); + Stream descendants = ProcessHandle.current() + .descendants(); + descendants.filter(ProcessHandle::isAlive) + .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info() + .command())); + } + + @Test + public void givenProcess_whenAddExitCallback_thenSuccess() throws Exception { + String javaCmd = ProcessUtils.getJavaCmd() + .getAbsolutePath(); + ProcessBuilder processBuilder + = new ProcessBuilder(javaCmd, "-version"); + Process process = processBuilder.inheritIO() + .start(); + ProcessHandle processHandle = process.toHandle(); + + log.info("PID: {} has started", processHandle.getPid()); + CompletableFuture onProcessExit = processHandle.onExit(); + onProcessExit.get(); + assertEquals(false, processHandle.isAlive()); + onProcessExit.thenAccept(ph -> { + log.info("PID: {} has stopped", ph.getPid()); + }); + } + +} diff --git a/core-java/.gitignore b/core-java/.gitignore index 251a8755bd..2a03a0f72e 100644 --- a/core-java/.gitignore +++ b/core-java/.gitignore @@ -1,11 +1,14 @@ *.class +0.* + #folders# /target /neoDb* /data /src/main/webapp/WEB-INF/classes */META-INF/* +.resourceCache # Packaged files # *.jar diff --git a/core-java/0.004102810554955205 b/core-java/0.004102810554955205 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/0.04832801936270381 b/core-java/0.04832801936270381 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/0.5633433244738808 b/core-java/0.5633433244738808 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/0.5967303215007616 b/core-java/0.5967303215007616 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/0.6256429734439612 b/core-java/0.6256429734439612 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/0.9252611327674576 b/core-java/0.9252611327674576 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/0.9799201796740292 b/core-java/0.9799201796740292 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core-java/README.md b/core-java/README.md index 341dbdf910..a34908d8ae 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -58,3 +58,24 @@ - [Guide to java.util.concurrent.BlockingQueue](http://www.baeldung.com/java-blocking-queue) - [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch) - [How to Design a Genetic Algorithm in Java](http://www.baeldung.com/java-genetic-algorithm) +- [A Guide to ConcurrentMap](http://www.baeldung.com/java-concurrent-map) +- [Guide to PriorityBlockingQueue in Java](http://www.baeldung.com/java-priority-blocking-queue) +- [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector) +- [Avoiding the ConcurrentModificationException in Java](http://www.baeldung.com/java-concurrentmodificationexception) +- [Guide to WeakHashMap in Java](http://www.baeldung.com/java-weakhashmap) +- [Strategy Design Pattern in Java 8](http://www.baeldung.com/java-strategy-pattern) +- [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams) +- [Custom Thread Pools In Java 8 Parallel Streams](http://www.baeldung.com/java-8-parallel-streams-custom-threadpool) +- [String Operations with Java Streams](http://www.baeldung.com/java-stream-operations-on-strings) +- [Spring Security – Cache Control Headers](http://www.baeldung.com/spring-security-cache-control-headers) +- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions) +- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) +- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn) +- [Exceptions in Java 8 Lambda Expressions](http://www.baeldung.com/java-lambda-exceptions) +- [Guide to the Guava BiMap](http://www.baeldung.com/guava-bimap) +- [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream) +- [Java 8 Stream findFirst() vs. findAny()](http://www.baeldung.com/java-stream-findfirst-vs-findany) +- [Chained Exceptions in Java](http://www.baeldung.com/java-chained-exceptions) +- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap) +- [A Guide to LinkedHashMap in Java](http://www.baeldung.com/java-linked-hashmap) +- [A Guide to TreeMap in Java](http://www.baeldung.com/java-treemap) diff --git a/core-java/pom.xml b/core-java/pom.xml index b2c59989f1..225eb3fc29 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -165,6 +165,12 @@ commons-codec ${commons-codec.version} + + + org.javamoney + moneta + 1.1 + diff --git a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java b/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java index 3f7c8bf4b3..22c5776293 100644 --- a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java +++ b/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java @@ -2,7 +2,8 @@ package com.baeldung.algorithms; import java.util.Scanner; -import com.baeldung.algorithms.annealing.SimulatedAnnealing; +import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing; +import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization; import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm; import com.baeldung.algorithms.slope_one.SlopeOne; @@ -14,6 +15,7 @@ public class RunAlgorithm { System.out.println("1 - Simulated Annealing"); System.out.println("2 - Slope One"); System.out.println("3 - Simple Genetic Algorithm"); + System.out.println("4 - Ant Colony"); int decision = in.nextInt(); switch (decision) { case 1: @@ -27,6 +29,10 @@ public class RunAlgorithm { SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm(); ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111"); break; + case 4: + AntColonyOptimization antColony = new AntColonyOptimization(21); + antColony.startAntOptimization(); + break; default: System.out.println("Unknown option"); break; diff --git a/core-java/src/main/java/com/baeldung/algorithms/annealing/City.java b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java similarity index 90% rename from core-java/src/main/java/com/baeldung/algorithms/annealing/City.java rename to core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java index 77e8652df0..cb5647f4d2 100644 --- a/core-java/src/main/java/com/baeldung/algorithms/annealing/City.java +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java @@ -1,4 +1,4 @@ -package com.baeldung.algorithms.annealing; +package com.baeldung.algorithms.ga.annealing; import lombok.Data; diff --git a/core-java/src/main/java/com/baeldung/algorithms/annealing/SimulatedAnnealing.java b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java similarity index 96% rename from core-java/src/main/java/com/baeldung/algorithms/annealing/SimulatedAnnealing.java rename to core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java index a7dc974e97..bff64fc239 100644 --- a/core-java/src/main/java/com/baeldung/algorithms/annealing/SimulatedAnnealing.java +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java @@ -1,4 +1,4 @@ -package com.baeldung.algorithms.annealing; +package com.baeldung.algorithms.ga.annealing; public class SimulatedAnnealing { diff --git a/core-java/src/main/java/com/baeldung/algorithms/annealing/Travel.java b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java similarity index 97% rename from core-java/src/main/java/com/baeldung/algorithms/annealing/Travel.java rename to core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java index 9bf341fbbe..3139b49586 100644 --- a/core-java/src/main/java/com/baeldung/algorithms/annealing/Travel.java +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java @@ -1,4 +1,4 @@ -package com.baeldung.algorithms.annealing; +package com.baeldung.algorithms.ga.annealing; import java.util.ArrayList; import java.util.Collections; diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java new file mode 100644 index 0000000000..4ea23b799f --- /dev/null +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java @@ -0,0 +1,37 @@ +package com.baeldung.algorithms.ga.ant_colony; + +public class Ant { + + protected int trailSize; + protected int trail[]; + protected boolean visited[]; + + public Ant(int tourSize) { + this.trailSize = tourSize; + this.trail = new int[tourSize]; + this.visited = new boolean[tourSize]; + } + + protected void visitCity(int currentIndex, int city) { + trail[currentIndex + 1] = city; + visited[city] = true; + } + + protected boolean visited(int i) { + return visited[i]; + } + + protected double trailLength(double graph[][]) { + double length = graph[trail[trailSize - 1]][trail[0]]; + for (int i = 0; i < trailSize - 1; i++) { + length += graph[trail[i]][trail[i + 1]]; + } + return length; + } + + protected void clear() { + for (int i = 0; i < trailSize; i++) + visited[i] = false; + } + +} diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java new file mode 100644 index 0000000000..27a270f906 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java @@ -0,0 +1,207 @@ +package com.baeldung.algorithms.ga.ant_colony; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.stream.IntStream; + +public class AntColonyOptimization { + + private double c = 1.0; + private double alpha = 1; + private double beta = 5; + private double evaporation = 0.5; + private double Q = 500; + private double antFactor = 0.8; + private double randomFactor = 0.01; + + private int maxIterations = 1000; + + public int numberOfCities; + public int numberOfAnts; + private double graph[][]; + private double trails[][]; + private List ants = new ArrayList<>(); + private Random random = new Random(); + private double probabilities[]; + + private int currentIndex; + + public int[] bestTourOrder; + public double bestTourLength; + + public AntColonyOptimization(int noOfCities) { + graph = generateRandomMatrix(noOfCities); + numberOfCities = graph.length; + numberOfAnts = (int) (numberOfCities * antFactor); + + trails = new double[numberOfCities][numberOfCities]; + probabilities = new double[numberOfCities]; + IntStream.range(0, numberOfAnts).forEach(i -> ants.add(new Ant(numberOfCities))); + } + + /** + * Generate initial solution + * + * @param n + * @return + */ + public double[][] generateRandomMatrix(int n) { + double[][] randomMatrix = new double[n][n]; + random.setSeed(System.currentTimeMillis()); + IntStream.range(0, n).forEach(i -> { + IntStream.range(0, n).forEach(j -> { + Integer r = random.nextInt(100) + 1; + randomMatrix[i][j] = Math.abs(r); + }); + }); + return randomMatrix; + } + + /** + * Perform ant optimization + * + * @return + */ + public void startAntOptimization() { + IntStream.rangeClosed(1, 3).forEach(i -> { + System.out.println("Attempt #" + i); + solve(); + }); + } + + /** + * Use this method to run the main logic + * + * @return + */ + public int[] solve() { + setupAnts(); + clearTrails(); + IntStream.range(0, maxIterations).forEach(i -> { + moveAnts(); + updateTrails(); + updateBest(); + }); + System.out.println("Best tour length: " + (bestTourLength - numberOfCities)); + System.out.println("Best tour order: " + Arrays.toString(bestTourOrder)); + return bestTourOrder.clone(); + } + + /** + * Prepare ants for the simulation + */ + private void setupAnts() { + IntStream.range(0, numberOfAnts).forEach(i -> { + ants.stream().forEach(ant -> { + ant.clear(); + ant.visitCity(-1, random.nextInt(numberOfCities)); + }); + }); + currentIndex = 0; + } + + /** + * At each iteration, move ants + */ + private void moveAnts() { + IntStream.range(currentIndex, numberOfCities - 1).forEach(i -> { + ants.stream().forEach(ant -> { + ant.visitCity(currentIndex, selectNextCity(ant)); + }); + currentIndex++; + }); + } + + /** + * Select next city for each ant + * + * @param ant + * @return + */ + private int selectNextCity(Ant ant) { + int t = random.nextInt(numberOfCities - currentIndex); + if (random.nextDouble() < randomFactor) { + IntStream.range(0, numberOfCities).filter(i -> i == t && !ant.visited(i)).findFirst(); + } + calculateProbabilities(ant); + double r = random.nextDouble(); + double total = 0; + for (int i = 0; i < numberOfCities; i++) { + total += probabilities[i]; + if (total >= r) { + return i; + } + } + + throw new RuntimeException("There are no other cities"); + } + + /** + * Calculate the next city picks probabilites + * + * @param ant + */ + public void calculateProbabilities(Ant ant) { + int i = ant.trail[currentIndex]; + double pheromone = 0.0; + for (int l = 0; l < numberOfCities; l++) { + if (!ant.visited(l)) { + pheromone += Math.pow(trails[i][l], alpha) * Math.pow(1.0 / graph[i][l], beta); + } + } + for (int j = 0; j < numberOfCities; j++) { + if (ant.visited(j)) { + probabilities[j] = 0.0; + } else { + double numerator = Math.pow(trails[i][j], alpha) * Math.pow(1.0 / graph[i][j], beta); + probabilities[j] = numerator / pheromone; + } + } + } + + /** + * Update trails that ants used + */ + private void updateTrails() { + for (int i = 0; i < numberOfCities; i++) { + for (int j = 0; j < numberOfCities; j++) { + trails[i][j] *= evaporation; + } + } + for (Ant a : ants) { + double contribution = Q / a.trailLength(graph); + for (int i = 0; i < numberOfCities - 1; i++) { + trails[a.trail[i]][a.trail[i + 1]] += contribution; + } + trails[a.trail[numberOfCities - 1]][a.trail[0]] += contribution; + } + } + + /** + * Update the best solution + */ + private void updateBest() { + if (bestTourOrder == null) { + bestTourOrder = ants.get(0).trail; + bestTourLength = ants.get(0).trailLength(graph); + } + for (Ant a : ants) { + if (a.trailLength(graph) < bestTourLength) { + bestTourLength = a.trailLength(graph); + bestTourOrder = a.trail.clone(); + } + } + } + + /** + * Clear trails after simulation + */ + private void clearTrails() { + IntStream.range(0, numberOfCities).forEach(i -> { + IntStream.range(0, numberOfCities).forEach(j -> trails[i][j] = c); + }); + } + +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java b/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java new file mode 100644 index 0000000000..4f061d2efd --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java @@ -0,0 +1,83 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Stack; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import static java.lang.Thread.sleep; + +public class ReentrantLockWithCondition { + + static Logger logger = LoggerFactory.getLogger(ReentrantLockWithCondition.class); + + Stack stack = new Stack<>(); + int CAPACITY = 5; + + ReentrantLock lock = new ReentrantLock(); + Condition stackEmptyCondition = lock.newCondition(); + Condition stackFullCondition = lock.newCondition(); + + public void pushToStack(String item) throws InterruptedException { + try { + lock.lock(); + if (stack.size() == CAPACITY) { + logger.info(Thread.currentThread().getName() + " wait on stack full"); + stackFullCondition.await(); + } + logger.info("Pushing the item " + item); + stack.push(item); + stackEmptyCondition.signalAll(); + } finally { + lock.unlock(); + } + + } + + public String popFromStack() throws InterruptedException { + try { + lock.lock(); + if (stack.size() == 0) { + logger.info(Thread.currentThread().getName() + " wait on stack empty"); + stackEmptyCondition.await(); + } + return stack.pop(); + } finally { + stackFullCondition.signalAll(); + lock.unlock(); + } + } + + public static void main(String[] args) { + final int threadCount = 2; + ReentrantLockWithCondition object = new ReentrantLockWithCondition(); + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + service.execute(() -> { + for (int i = 0; i < 10; i++) { + try { + object.pushToStack("Item " + i); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + }); + + service.execute(() -> { + for (int i = 0; i < 10; i++) { + try { + logger.info("Item popped " + object.popFromStack()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + }); + + service.shutdown(); + } +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java b/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java new file mode 100644 index 0000000000..b6a4615638 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java @@ -0,0 +1,92 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +import static java.lang.Thread.sleep; + +public class SharedObjectWithLock { + + Logger logger = LoggerFactory.getLogger(SharedObjectWithLock.class); + + ReentrantLock lock = new ReentrantLock(true); + + int counter = 0; + + public void perform() { + + lock.lock(); + logger.info("Thread - " + Thread.currentThread().getName() + " acquired the lock"); + try { + logger.info("Thread - " + Thread.currentThread().getName() + " processing"); + counter++; + } catch (Exception exception) { + logger.error(" Interrupted Exception ", exception); + } finally { + lock.unlock(); + logger.info("Thread - " + Thread.currentThread().getName() + " released the lock"); + } + } + + public void performTryLock() { + + logger.info("Thread - " + Thread.currentThread().getName() + " attempting to acquire the lock"); + try { + boolean isLockAcquired = lock.tryLock(2, TimeUnit.SECONDS); + if (isLockAcquired) { + try { + logger.info("Thread - " + Thread.currentThread().getName() + " acquired the lock"); + + logger.info("Thread - " + Thread.currentThread().getName() + " processing"); + sleep(1000); + } finally { + lock.unlock(); + logger.info("Thread - " + Thread.currentThread().getName() + " released the lock"); + + } + } + } catch (InterruptedException exception) { + logger.error(" Interrupted Exception ", exception); + } + logger.info("Thread - " + Thread.currentThread().getName() + " could not acquire the lock"); + } + + public ReentrantLock getLock() { + return lock; + } + + boolean isLocked() { + return lock.isLocked(); + } + + boolean hasQueuedThreads() { + return lock.hasQueuedThreads(); + } + + int getCounter() { + return counter; + } + + public static void main(String[] args) { + + final int threadCount = 2; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + final SharedObjectWithLock object = new SharedObjectWithLock(); + + service.execute(() -> { + object.perform(); + }); + service.execute(() -> { + object.performTryLock(); + }); + + service.shutdown(); + + } + +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java b/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java new file mode 100644 index 0000000000..0b0dbc72cb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java @@ -0,0 +1,104 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.StampedLock; + +import static java.lang.Thread.sleep; + +public class StampedLockDemo { + Map map = new HashMap<>(); + Logger logger = LoggerFactory.getLogger(StampedLockDemo.class); + + private final StampedLock lock = new StampedLock(); + + public void put(String key, String value) throws InterruptedException { + long stamp = lock.writeLock(); + + try { + logger.info(Thread.currentThread().getName() + " acquired the write lock with stamp " + stamp); + map.put(key, value); + } finally { + lock.unlockWrite(stamp); + logger.info(Thread.currentThread().getName() + " unlocked the write lock with stamp " + stamp); + } + } + + public String get(String key) throws InterruptedException { + long stamp = lock.readLock(); + logger.info(Thread.currentThread().getName() + " acquired the read lock with stamp " + stamp); + try { + sleep(5000); + return map.get(key); + + } finally { + lock.unlockRead(stamp); + logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp); + + } + + } + + public String readWithOptimisticLock(String key) throws InterruptedException { + long stamp = lock.tryOptimisticRead(); + String value = map.get(key); + + if (!lock.validate(stamp)) { + stamp = lock.readLock(); + try { + sleep(5000); + return map.get(key); + + } finally { + lock.unlock(stamp); + logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp); + + } + } + return value; + } + + public static void main(String[] args) { + final int threadCount = 4; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + StampedLockDemo object = new StampedLockDemo(); + + Runnable writeTask = () -> { + + try { + object.put("key1", "value1"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + Runnable readTask = () -> { + + try { + object.get("key1"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + Runnable readOptimisticTask = () -> { + + try { + object.readWithOptimisticLock("key1"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + service.submit(writeTask); + service.submit(writeTask); + service.submit(readTask); + service.submit(readOptimisticTask); + + service.shutdown(); + + } + +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java b/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java new file mode 100644 index 0000000000..83b8b34fe9 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java @@ -0,0 +1,120 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static java.lang.Thread.sleep; + +public class SynchronizedHashMapWithRWLock { + + static Map syncHashMap = new HashMap<>(); + Logger logger = LoggerFactory.getLogger(SynchronizedHashMapWithRWLock.class); + + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + + public void put(String key, String value) throws InterruptedException { + + try { + writeLock.lock(); + logger.info(Thread.currentThread().getName() + " writing"); + syncHashMap.put(key, value); + sleep(1000); + } finally { + writeLock.unlock(); + } + + } + + public String get(String key) { + try { + readLock.lock(); + logger.info(Thread.currentThread().getName() + " reading"); + return syncHashMap.get(key); + } finally { + readLock.unlock(); + } + } + + public String remove(String key) { + try { + writeLock.lock(); + return syncHashMap.remove(key); + } finally { + writeLock.unlock(); + } + } + + public boolean containsKey(String key) { + try { + readLock.lock(); + return syncHashMap.containsKey(key); + } finally { + readLock.unlock(); + } + } + + boolean isReadLockAvailable() { + return readLock.tryLock(); + } + + public static void main(String[] args) throws InterruptedException { + + final int threadCount = 3; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock(); + + service.execute(new Thread(new Writer(object), "Writer")); + service.execute(new Thread(new Reader(object), "Reader1")); + service.execute(new Thread(new Reader(object), "Reader2")); + + service.shutdown(); + } + + private static class Reader implements Runnable { + + SynchronizedHashMapWithRWLock object; + + public Reader(SynchronizedHashMapWithRWLock object) { + this.object = object; + } + + @Override + public void run() { + for (int i = 0; i < 10; i++) { + object.get("key" + i); + } + } + } + + private static class Writer implements Runnable { + + SynchronizedHashMapWithRWLock object; + + public Writer(SynchronizedHashMapWithRWLock object) { + this.object = object; + } + + @Override + public void run() { + for (int i = 0; i < 10; i++) { + try { + object.put("key" + i, "value" + i); + sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + +} diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Pen.java b/core-java/src/main/java/com/baeldung/list/listoflist/Pen.java new file mode 100644 index 0000000000..efbd88d0b1 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/list/listoflist/Pen.java @@ -0,0 +1,18 @@ +package com.baeldung.list.listoflist; + +public class Pen implements Stationery { + + public String name; + + public Pen(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Pencil.java b/core-java/src/main/java/com/baeldung/list/listoflist/Pencil.java new file mode 100644 index 0000000000..7dfa119703 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/list/listoflist/Pencil.java @@ -0,0 +1,18 @@ +package com.baeldung.list.listoflist; + +public class Pencil implements Stationery{ + + public String name; + + public Pencil(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Rubber.java b/core-java/src/main/java/com/baeldung/list/listoflist/Rubber.java new file mode 100644 index 0000000000..7511139e14 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/list/listoflist/Rubber.java @@ -0,0 +1,18 @@ +package com.baeldung.list.listoflist; + +public class Rubber implements Stationery { + + public String name; + + public Rubber(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Stationery.java b/core-java/src/main/java/com/baeldung/list/listoflist/Stationery.java new file mode 100644 index 0000000000..d914397cb8 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/list/listoflist/Stationery.java @@ -0,0 +1,5 @@ +package com.baeldung.list.listoflist; + +public interface Stationery { + +} diff --git a/core-java/src/main/java/com/baeldung/money/JavaMoney.java b/core-java/src/main/java/com/baeldung/money/JavaMoney.java new file mode 100644 index 0000000000..3171d226ed --- /dev/null +++ b/core-java/src/main/java/com/baeldung/money/JavaMoney.java @@ -0,0 +1,151 @@ +package com.baeldung.money; + +import java.util.Locale; +import java.util.logging.Logger; + +import javax.money.CurrencyUnit; +import javax.money.Monetary; +import javax.money.MonetaryAmount; +import javax.money.UnknownCurrencyException; +import javax.money.convert.ConversionQueryBuilder; +import javax.money.convert.CurrencyConversion; +import javax.money.convert.MonetaryConversions; +import javax.money.format.AmountFormatQueryBuilder; +import javax.money.format.MonetaryAmountFormat; +import javax.money.format.MonetaryFormats; + +import org.javamoney.moneta.FastMoney; +import org.javamoney.moneta.Money; +import org.javamoney.moneta.format.CurrencyStyle; + +public class JavaMoney { + final static Logger LOGGER = Logger.getLogger(JavaMoney.class.getName()); + CurrencyUnit USD; + MonetaryAmount fstAmtUSD; + MonetaryAmount fstAmtEUR; + MonetaryAmount oneDolar; + MonetaryAmount moneyof; + MonetaryAmount fastmoneyof; + MonetaryAmount roundEUR; + MonetaryAmount calcAmtUSD; + MonetaryAmount[] monetaryAmounts; + MonetaryAmount sumAmtCHF; + MonetaryAmount calcMoneyFastMoney; + MonetaryAmount convertedAmountEURtoUSD; + MonetaryAmount convertedAmountEURtoUSD2; + MonetaryAmount convertedAmountUSDtoEUR; + MonetaryAmount convertedAmountUSDtoEUR2; + MonetaryAmount multiplyAmount; + MonetaryAmount divideAmount; + MonetaryAmount oneDivThree; + CurrencyConversion convEUR; + CurrencyConversion convUSD; + CurrencyConversion conversionUSD; + CurrencyConversion conversionEUR; + MonetaryAmount oneEuro; + MonetaryAmountFormat formatUSD; + MonetaryAmountFormat customFormat; + String usFormatted; + String customFormatted; + + public JavaMoney() { + USD = Monetary.getCurrency("USD"); + fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(USD).setNumber(200.50).create(); + fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); + oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + moneyof = Money.of(12, USD); + fastmoneyof = FastMoney.of(2, USD); + + LOGGER.info("First Amount in USD : " + fstAmtUSD); + LOGGER.info("First Amount in EUR : " + fstAmtEUR); + LOGGER.info("One Dolar : " + oneDolar); + LOGGER.info("MoneyOf : " + moneyof); + LOGGER.info("FastMoneyOf : " + fastmoneyof); + + try{ + @SuppressWarnings("unused") + CurrencyUnit AAA = Monetary.getCurrency("AAA"); + } catch (UnknownCurrencyException e) { + LOGGER.severe("Unknown Currency"); + } + + roundEUR = fstAmtEUR.with(Monetary.getDefaultRounding()); + + LOGGER.info("Rounded EUR : " + roundEUR); + + calcAmtUSD = Money.of(1, "USD").subtract(fstAmtUSD); + + LOGGER.info("Substracting amounts : " + calcAmtUSD); + + calcMoneyFastMoney = moneyof.subtract(fastmoneyof); + + LOGGER.info("Money & FastMoney operations : " + calcMoneyFastMoney); + + monetaryAmounts = + new MonetaryAmount[] { + Money.of(100, "CHF"), + Money.of(10.20, "CHF"), + Money.of(1.15, "CHF"), }; + sumAmtCHF = Money.of(0, "CHF"); + for (MonetaryAmount monetaryAmount : monetaryAmounts) { + sumAmtCHF = sumAmtCHF.add(monetaryAmount); + } + + LOGGER.info("Adding amounts : " + sumAmtCHF); + + multiplyAmount = oneDolar.multiply(0.25); + LOGGER.info("Multiply Amount : " + multiplyAmount); + + divideAmount = oneDolar.divide(0.25); + LOGGER.info("Divide Amount : " + divideAmount); + + try{ + oneDivThree = oneDolar.divide(3); + }catch (ArithmeticException e) { + LOGGER.severe("One divide by Three is an infinite number"); + } + + convEUR = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency("EUR").build()); + convUSD = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency(USD).build()); + + conversionUSD = MonetaryConversions.getConversion("USD"); + conversionEUR = MonetaryConversions.getConversion("EUR"); + + convertedAmountEURtoUSD = fstAmtEUR.with(conversionUSD); + convertedAmountEURtoUSD2 = fstAmtEUR.with(convUSD); + convertedAmountUSDtoEUR = oneDolar.with(conversionEUR); + convertedAmountUSDtoEUR2 = oneDolar.with(convEUR); + LOGGER.info("C1 - " + convertedAmountEURtoUSD); + LOGGER.info("C2 - " + convertedAmountEURtoUSD2); + LOGGER.info("One Euro -> " + convertedAmountUSDtoEUR); + LOGGER.info("One Euro2 -> " + convertedAmountUSDtoEUR2); + + oneEuro = Money.of(1, "EUR"); + + if (oneEuro.equals(FastMoney.of(1, "EUR"))) { + LOGGER.info("Money == FastMoney"); + } else { + LOGGER.info("Money != FastMoney"); + } + + if (oneDolar.equals(Money.of(1, "USD"))) { + LOGGER.info("Factory == Money"); + } else { + LOGGER.info("Factory != Money"); + } + + formatUSD = MonetaryFormats.getAmountFormat(Locale.US); + usFormatted = formatUSD.format(oneDolar); + LOGGER.info("One dolar standard formatted : " + usFormatted); + + customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.of(Locale.US).set(CurrencyStyle.NAME).set("pattern", "00000.00 ¤").build()); + customFormatted = customFormat.format(oneDolar); + LOGGER.info("One dolar custom formatted : " + customFormatted); + } + + public static void main(String[] args) { + @SuppressWarnings("unused") + JavaMoney java9Money = new JavaMoney(); + } + +} diff --git a/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java b/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java new file mode 100644 index 0000000000..4137b5af00 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java @@ -0,0 +1,125 @@ +package com.baeldung.primitiveconversions; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author paulo.motta + */ +public class PrimitiveConversionsJUnitTest { + + @Test + public void givenDataWithLessBits_whenAttributingToLargerSizeVariable_thenNoSpecialNotation() { + int myInt = 127; + + long myLong = myInt; + assertEquals(127L, myLong); + + float myFloat = myLong; + assertEquals(127.0f, myFloat, 0.00001f); + + double myDouble = myLong; + assertEquals(127.0, myDouble,0.00001); + } + + @Test + public void givenDataWithMoreBits_whenAttributingToSmallerSizeVariable_thenCastOperatorNeeded() { + + long myLong = 127L; + double myDouble = 127.0; + + float myFloat = (float) myDouble; + assertEquals(127.0f, myFloat, 0.00001f); + + int myInt = (int) myLong; + assertEquals(127, myInt); + + byte myByte = (byte) myInt; + assertEquals( ((byte)127), myByte); + } + + @Test + public void givenPrimitiveData_whenAssiginingToWrapper_thenAutomaticBoxingHappens(){ + int myInt = 127; + + Integer myIntegerReference = myInt; + assertEquals(new Integer("127"), myIntegerReference); + + } + + @Test + public void givenWrapperObjectData_whenAssiginingToPrimitive_thenAutomaticUnboxingHappens(){ + Integer myIntegerReference = new Integer("127"); + + int myOtherInt = myIntegerReference; + assertEquals(127, myOtherInt); + + } + + @Test + public void givenByteValue_whenConvertingToChar_thenWidenAndNarrowTakesPlace(){ + byte myLargeValueByte = (byte) 130; //0b10000010 + System.out.println(myLargeValueByte); //0b10000010 -126 + assertEquals( -126, myLargeValueByte); + + int myLargeValueInt = myLargeValueByte; + System.out.println(myLargeValueInt); //0b11111111 11111111 11111111 10000010 -126 + assertEquals( -126, myLargeValueInt); + + char myLargeValueChar = (char) myLargeValueByte; + System.out.println(myLargeValueChar);//0b11111111 10000010 unsigned 0xFF82 + assertEquals(0xFF82, myLargeValueChar); + + myLargeValueInt = myLargeValueChar; + System.out.println(myLargeValueInt); //0b11111111 10000010 65410 + assertEquals(65410, myLargeValueInt); + + byte myOtherByte = (byte) myLargeValueInt; + System.out.println(myOtherByte); //0b10000010 -126 + assertEquals( -126, myOtherByte); + + + char myLargeValueChar2 = 130; //This is an int not a byte! + System.out.println(myLargeValueChar2);//0b00000000 10000010 unsigned 0x0082 + assertEquals(0x0082, myLargeValueChar2); + + int myLargeValueInt2 = myLargeValueChar2; + System.out.println(myLargeValueInt2); //0b00000000 10000010 130 + assertEquals(130, myLargeValueInt2); + + byte myOtherByte2 = (byte) myLargeValueInt2; + System.out.println(myOtherByte2); //0b10000010 -126 + assertEquals( -126, myOtherByte2); + } + + @Test + public void givenString_whenParsingWithWrappers_thenValuesAreReturned(){ + String myString = "127"; + + byte myNewByte = Byte.parseByte(myString); + assertEquals( ((byte)127), myNewByte); + + short myNewShort = Short.parseShort(myString); + assertEquals( ((short)127), myNewShort); + + int myNewInt = Integer.parseInt(myString); + assertEquals( 127, myNewInt); + + long myNewLong = Long.parseLong(myString); + assertEquals( 127L, myNewLong); + + float myNewFloat = Float.parseFloat(myString); + assertEquals( 127.0f, myNewFloat, 0.00001f); + + double myNewDouble = Double.parseDouble(myString); + assertEquals( 127.0, myNewDouble, 0.00001f); + + boolean myNewBoolean = Boolean.parseBoolean(myString); + assertEquals( false, myNewBoolean); //numbers are not true! + + char myNewChar = myString.charAt(0); + assertEquals( 49, myNewChar); //the value of '1' + } + +} diff --git a/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java b/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java new file mode 100644 index 0000000000..40d2464ab6 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java @@ -0,0 +1,22 @@ +package com.baeldung.algorithms; + +import org.junit.Assert; +import org.junit.Test; + +import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization; + +public class AntColonyOptimizationTest { + + @Test + public void testGenerateRandomMatrix() { + AntColonyOptimization antTSP = new AntColonyOptimization(5); + Assert.assertNotNull(antTSP.generateRandomMatrix(5)); + } + + @Test + public void testStartAntOptimization() { + AntColonyOptimization antTSP = new AntColonyOptimization(5); + Assert.assertNotNull(antTSP.solve()); + } + +} diff --git a/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java b/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java index 2fc7ea9b92..6822bae990 100644 --- a/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java +++ b/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java @@ -3,7 +3,7 @@ package com.baeldung.algorithms; import org.junit.Assert; import org.junit.Test; -import com.baeldung.algorithms.annealing.SimulatedAnnealing; +import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing; public class SimulatedAnnealingTest { diff --git a/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java new file mode 100644 index 0000000000..9b82ced642 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java @@ -0,0 +1,75 @@ +package com.baeldung.concurrent.locks; + +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static junit.framework.TestCase.assertEquals; + +public class SharedObjectWithLockManualTest { + + @Test + public void whenLockAcquired_ThenLockedIsTrue() { + final SharedObjectWithLock object = new SharedObjectWithLock(); + + final int threadCount = 2; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeThreads(object, threadCount, service); + + assertEquals(true, object.isLocked()); + + service.shutdown(); + } + + @Test + public void whenLocked_ThenQueuedThread() { + final int threadCount = 4; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + final SharedObjectWithLock object = new SharedObjectWithLock(); + + executeThreads(object, threadCount, service); + + assertEquals(object.hasQueuedThreads(), true); + + service.shutdown(); + + } + + public void whenTryLock_ThenQueuedThread() { + final SharedObjectWithLock object = new SharedObjectWithLock(); + + final int threadCount = 2; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeThreads(object, threadCount, service); + + assertEquals(true, object.isLocked()); + + service.shutdown(); + } + + @Test + public void whenGetCount_ThenCorrectCount() throws InterruptedException { + final int threadCount = 4; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + final SharedObjectWithLock object = new SharedObjectWithLock(); + + executeThreads(object, threadCount, service); + Thread.sleep(1000); + assertEquals(object.getCounter(), 4); + + service.shutdown(); + + } + + private void executeThreads(SharedObjectWithLock object, int threadCount, ExecutorService service) { + for (int i = 0; i < threadCount; i++) { + service.execute(() -> { + object.perform(); + }); + } + } + +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java new file mode 100644 index 0000000000..fd6cf08442 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java @@ -0,0 +1,58 @@ +package com.baeldung.concurrent.locks; + +import jdk.nashorn.internal.ir.annotations.Ignore; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static junit.framework.TestCase.assertEquals; + +public class SynchronizedHashMapWithRWLockManualTest { + + @Test + public void whenWriting_ThenNoReading() { + SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock(); + final int threadCount = 3; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeWriterThreads(object, threadCount, service); + + assertEquals(object.isReadLockAvailable(), false); + + service.shutdown(); + } + + @Test + public void whenReading_ThenMultipleReadingAllowed() { + SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock(); + final int threadCount = 5; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeReaderThreads(object, threadCount, service); + + assertEquals(object.isReadLockAvailable(), true); + + service.shutdown(); + } + + private void executeWriterThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) { + for (int i = 0; i < threadCount; i++) { + service.execute(() -> { + try { + object.put("key" + threadCount, "value" + threadCount); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + } + + private void executeReaderThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) { + for (int i = 0; i < threadCount; i++) + service.execute(() -> { + object.get("key" + threadCount); + }); + } + +} diff --git a/core-java/src/test/java/com/baeldung/java/map/README.md b/core-java/src/test/java/com/baeldung/java/map/README.md deleted file mode 100644 index 0bba153763..0000000000 --- a/core-java/src/test/java/com/baeldung/java/map/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap) diff --git a/core-java/src/test/java/com/baeldung/list/listoflist/ListOfListsTest.java b/core-java/src/test/java/com/baeldung/list/listoflist/ListOfListsTest.java new file mode 100644 index 0000000000..674a2f89bc --- /dev/null +++ b/core-java/src/test/java/com/baeldung/list/listoflist/ListOfListsTest.java @@ -0,0 +1,76 @@ +package com.baeldung.list.listoflist; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; + +public class ListOfListsTest { + + private List> listOfLists = new ArrayList>(); + private ArrayList penList = new ArrayList<>(); + private ArrayList pencilList = new ArrayList<>(); + private ArrayList rubberList = new ArrayList<>(); + + @SuppressWarnings("unchecked") + @Before + public void init() { + listOfLists.add(penList); + listOfLists.add(pencilList); + listOfLists.add(rubberList); + + ((ArrayList) listOfLists.get(0)).add(new Pen("Pen 1")); + ((ArrayList) listOfLists.get(1)).add(new Pencil("Pencil 1")); + ((ArrayList) listOfLists.get(2)).add(new Rubber("Rubber 1")); + } + + @Test + public void givenListOfLists_thenCheckNames() { + assertEquals("Pen 1", ((Pen) listOfLists.get(0) + .get(0)).getName()); + assertEquals("Pencil 1", ((Pencil) listOfLists.get(1) + .get(0)).getName()); + assertEquals("Rubber 1", ((Rubber) listOfLists.get(2) + .get(0)).getName()); + } + + @SuppressWarnings("unchecked") + @Test + public void givenListOfLists_whenRemovingElements_thenCheckNames() { + + ((ArrayList) listOfLists.get(1)).remove(0); + listOfLists.remove(1); + assertEquals("Rubber 1", ((Rubber) listOfLists.get(1) + .get(0)).getName()); + listOfLists.remove(0); + assertEquals("Rubber 1", ((Rubber) listOfLists.get(0) + .get(0)).getName()); + } + + @Test + public void givenThreeList_whenCombineIntoOneList_thenCheckList() { + ArrayList pens = new ArrayList<>(); + pens.add(new Pen("Pen 1")); + pens.add(new Pen("Pen 2")); + ArrayList pencils = new ArrayList<>(); + pencils.add(new Pencil("Pencil 1")); + pencils.add(new Pencil("Pencil 2")); + ArrayList rubbers = new ArrayList<>(); + rubbers.add(new Rubber("Rubber 1")); + rubbers.add(new Rubber("Rubber 2")); + + List> list = new ArrayList>(); + list.add(pens); + list.add(pencils); + list.add(rubbers); + + assertEquals("Pen 1", ((Pen) list.get(0) + .get(0)).getName()); + assertEquals("Pencil 1", ((Pencil) list.get(1) + .get(0)).getName()); + assertEquals("Rubber 1", ((Rubber) list.get(2) + .get(0)).getName()); + } +} diff --git a/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java b/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java new file mode 100644 index 0000000000..3d2f986c30 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java @@ -0,0 +1,153 @@ +package com.baeldung.money; + +import org.javamoney.moneta.FastMoney; +import org.javamoney.moneta.Money; +import org.javamoney.moneta.format.CurrencyStyle; +import org.junit.Test; + +import javax.money.CurrencyUnit; +import javax.money.Monetary; +import javax.money.MonetaryAmount; +import javax.money.UnknownCurrencyException; +import javax.money.convert.ConversionQueryBuilder; +import javax.money.convert.CurrencyConversion; +import javax.money.convert.MonetaryConversions; +import javax.money.format.AmountFormatQueryBuilder; +import javax.money.format.MonetaryAmountFormat; +import javax.money.format.MonetaryFormats; +import java.util.Locale; + +import static org.junit.Assert.*; + +public class JavaMoneyTest { + + @Test + public void givenCurrencyCode_whenString_thanExist() { + CurrencyUnit usd = Monetary.getCurrency("USD"); + + assertNotNull(usd); + assertEquals(usd.getCurrencyCode(), "USD"); + assertEquals(usd.getNumericCode(), 840); + assertEquals(usd.getDefaultFractionDigits(), 2); + } + + @Test(expected = UnknownCurrencyException.class) + public void givenCurrencyCode_whenNoExist_thanThrowsError() { + Monetary.getCurrency("AAA"); + fail(); // if no exception + } + + @Test + public void givenAmounts_whenStringified_thanEquals() { + CurrencyUnit usd = Monetary.getCurrency("USD"); + MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(usd).setNumber(200).create(); + Money moneyof = Money.of(12, usd); + FastMoney fastmoneyof = FastMoney.of(2, usd); + + assertEquals("USD", usd.toString()); + assertEquals("USD 200", fstAmtUSD.toString()); + assertEquals("USD 12", moneyof.toString()); + assertEquals("USD 2.00000", fastmoneyof.toString()); + } + + @Test + public void givenCurrencies_whenCompared_thanNotequal() { + MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + Money oneEuro = Money.of(1, "EUR"); + + assertFalse(oneEuro.equals(FastMoney.of(1, "EUR"))); + assertTrue(oneDolar.equals(Money.of(1, "USD"))); + } + + @Test(expected = ArithmeticException.class) + public void givenAmount_whenDivided_thanThrowsException() { + MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + oneDolar.divide(3); + fail(); // if no exception + } + + @Test + public void givenAmounts_whenSummed_thanCorrect() { + MonetaryAmount[] monetaryAmounts = new MonetaryAmount[]{ + Money.of(100, "CHF"), Money.of(10.20, "CHF"), Money.of(1.15, "CHF")}; + + Money sumAmtCHF = Money.of(0, "CHF"); + for (MonetaryAmount monetaryAmount : monetaryAmounts) { + sumAmtCHF = sumAmtCHF.add(monetaryAmount); + } + + assertEquals("CHF 111.35", sumAmtCHF.toString()); + } + + @Test + public void givenArithmetic_whenStringified_thanEqualsAmount() { + CurrencyUnit usd = Monetary.getCurrency("USD"); + + Money moneyof = Money.of(12, usd); + MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(usd).setNumber(200.50).create(); + MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + Money subtractedAmount = Money.of(1, "USD").subtract(fstAmtUSD); + MonetaryAmount multiplyAmount = oneDolar.multiply(0.25); + MonetaryAmount divideAmount = oneDolar.divide(0.25); + + assertEquals("USD", usd.toString()); + assertEquals("USD 1", oneDolar.toString()); + assertEquals("USD 200.5", fstAmtUSD.toString()); + assertEquals("USD 12", moneyof.toString()); + assertEquals("USD -199.5", subtractedAmount.toString()); + assertEquals("USD 0.25", multiplyAmount.toString()); + assertEquals("USD 4", divideAmount.toString()); + } + + @Test + public void givenAmount_whenRounded_thanEquals() { + MonetaryAmount fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); + MonetaryAmount roundEUR = fstAmtEUR.with(Monetary.getDefaultRounding()); + assertEquals("EUR 1.30473908", fstAmtEUR.toString()); + assertEquals("EUR 1.3", roundEUR.toString()); + } + + @Test + public void givenAmount_whenCustomFormat_thanEquals() { + MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + MonetaryAmountFormat formatUSD = MonetaryFormats.getAmountFormat(Locale.US); + String usFormatted = formatUSD.format(oneDolar); + + MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.of(Locale.US).set(CurrencyStyle.NAME).set("pattern", "00000.00 ¤").build()); + String customFormatted = customFormat.format(oneDolar); + + assertEquals("USD 1", oneDolar.toString()); + assertNotNull(formatUSD); + assertNotNull(customFormat); + assertEquals("USD1.00", usFormatted); + assertEquals("00001.00 US Dollar", customFormatted); + } + + @Test + public void givenAmount_whenConversion_thenNotNull() { + CurrencyUnit USD = Monetary.getCurrency("USD"); + MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + MonetaryAmount fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); + + CurrencyConversion convEUR = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency("EUR").build()); + CurrencyConversion convUSD = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency(USD).build()); + + CurrencyConversion conversionUSD = MonetaryConversions.getConversion("USD"); + CurrencyConversion conversionEUR = MonetaryConversions.getConversion("EUR"); + + MonetaryAmount convertedAmountEURtoUSD = fstAmtEUR.with(conversionUSD); + MonetaryAmount convertedAmountEURtoUSD2 = fstAmtEUR.with(convUSD); + MonetaryAmount convertedAmountUSDtoEUR = oneDolar.with(conversionEUR); + MonetaryAmount convertedAmountUSDtoEUR2 = oneDolar.with(convEUR); + + assertEquals("USD", USD.toString()); + assertEquals("USD 1", oneDolar.toString()); + assertEquals("EUR 1.30473908", fstAmtEUR.toString()); + assertNotNull(convEUR); + assertNotNull(convUSD); + assertNotNull(convertedAmountEURtoUSD); + assertNotNull(convertedAmountEURtoUSD2); + assertNotNull(convertedAmountUSDtoEUR); + assertNotNull(convertedAmountUSDtoEUR2); + } +} diff --git a/couchbase-sdk/README.md b/couchbase-sdk/README.md index 9cdcdea012..f124a0192c 100644 --- a/couchbase-sdk/README.md +++ b/couchbase-sdk/README.md @@ -4,6 +4,7 @@ - [Introduction to Couchbase SDK for Java](http://www.baeldung.com/java-couchbase-sdk) - [Using Couchbase in a Spring Application](http://www.baeldung.com/couchbase-sdk-spring) - [Asynchronous Batch Opereations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) +- [Querying Couchbase with MapReduce Views](http://www.baeldung.com/couchbase-query-mapreduce-view) ### Overview This Maven project contains the Java code for the Couchbase entities and Spring services diff --git a/disruptor/README.md b/disruptor/README.md index e69de29bb2..779b1e89c4 100644 --- a/disruptor/README.md +++ b/disruptor/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Concurrency with LMAX Disruptor – An Introduction](http://www.baeldung.com/lmax-disruptor-concurrency) diff --git a/ejb/README.md b/ejb/README.md new file mode 100644 index 0000000000..08392bc80d --- /dev/null +++ b/ejb/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Guide to EJB Set-up](http://www.baeldung.com/ejb-intro) diff --git a/guava/README.md b/guava/README.md index 40e7f19f41..ee224bae5f 100644 --- a/guava/README.md +++ b/guava/README.md @@ -16,3 +16,11 @@ - [Guava – Sets](http://www.baeldung.com/guava-sets) - [Guava – Maps](http://www.baeldung.com/guava-maps) - [Guava Set + Function = Map](http://www.baeldung.com/guava-set-function-map-tutorial) +- [Guide to Guava’s Ordering](http://www.baeldung.com/guava-ordering) +- [Guide to Guava’s PreConditions](http://www.baeldung.com/guava-preconditions) +- [Introduction to Guava CacheLoader](http://www.baeldung.com/guava-cacheloader) +- [Guide to Guava’s EventBus](http://www.baeldung.com/guava-eventbus) +- [Guide to Guava Multimap](http://www.baeldung.com/guava-multimap) +- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) +- [Guide to Guava RangeMap](http://www.baeldung.com/guava-rangemap) +- [Guide to Guava Table](http://www.baeldung.com/guava-table) diff --git a/guava/src/test/java/org/baeldung/guava/GuavaReflectionUtilsTest.java b/guava/src/test/java/org/baeldung/guava/GuavaReflectionUtilsTest.java new file mode 100644 index 0000000000..e59a682e08 --- /dev/null +++ b/guava/src/test/java/org/baeldung/guava/GuavaReflectionUtilsTest.java @@ -0,0 +1,150 @@ +package org.baeldung.guava; + + +import com.google.common.collect.Lists; +import com.google.common.reflect.Invokable; +import com.google.common.reflect.TypeToken; +import org.junit.Test; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GuavaReflectionUtilsTest { + + @Test + public void givenTwoGenericList_whenCheckIsAssignableFrom_thenReturnTrueDueToTypeErasure() { + //given + ArrayList stringList = Lists.newArrayList(); + ArrayList intList = Lists.newArrayList(); + + //when + boolean result = stringList.getClass().isAssignableFrom(intList.getClass()); + + //then + assertTrue(result); + } + + @Test + public void givenTypeToken_whenResolveType_thenShouldResolveProperType() { + //given + TypeToken> stringListToken = new TypeToken>() { + }; + TypeToken> integerListToken = new TypeToken>() { + }; + TypeToken> numberTypeToken = new TypeToken>() { + }; + + //then + assertFalse(stringListToken.isSubtypeOf(integerListToken)); + assertFalse(numberTypeToken.isSubtypeOf(integerListToken)); + assertTrue(integerListToken.isSubtypeOf(numberTypeToken)); + } + + @Test + public void givenCustomClass_whenCaptureGeneric_thenReturnTypeAtRuntime() { + //given + ParametrizedClass parametrizedClass = new ParametrizedClass() { + }; + + //then + assertEquals(parametrizedClass.type, TypeToken.of(String.class)); + } + + @Test + public void givenComplexType_whenGetTypeArgument_thenShouldReturnTypeAtRuntime() { + //given + TypeToken> funToken = new TypeToken>() { + }; + + //when + TypeToken funResultToken = funToken.resolveType(Function.class.getTypeParameters()[1]); + + //then + assertEquals(funResultToken, TypeToken.of(String.class)); + } + + + @Test + public void givenMapType_whenGetTypeArgumentOfEntry_thenShouldReturnTypeAtRuntime() throws NoSuchMethodException { + //given + TypeToken> mapToken = new TypeToken>() { + }; + + //when + TypeToken entrySetToken = mapToken.resolveType(Map.class.getMethod("entrySet").getGenericReturnType()); + + //then + assertEquals(entrySetToken, new TypeToken>>() { + }); + } + + @Test + public void givenInvokable_whenCheckPublicMethod_shouldReturnTrue() throws NoSuchMethodException { + //given + Method method = CustomClass.class.getMethod("somePublicMethod"); + Invokable invokable = new TypeToken() { + }.method(method); + + //when + boolean isPublicStandradJava = Modifier.isPublic(method.getModifiers()); + boolean isPublicGuava = invokable.isPublic(); + //then + assertTrue(isPublicStandradJava); + assertTrue(isPublicGuava); + } + + @Test + public void givenInvokable_whenCheckFinalMethod_shouldReturnFalseForIsOverridable() throws NoSuchMethodException { + //given + Method method = CustomClass.class.getMethod("notOverridablePublicMethod"); + Invokable invokable = new TypeToken() { + }.method(method); + + //when + boolean isOverridableStandardJava = (!(Modifier.isFinal(method.getModifiers()) || Modifier.isPrivate(method.getModifiers()) + || Modifier.isStatic(method.getModifiers()) + || Modifier.isFinal(method.getDeclaringClass().getModifiers()))); + boolean isOverridableFinalGauava = invokable.isOverridable(); + + //then + assertFalse(isOverridableStandardJava); + assertFalse(isOverridableFinalGauava); + } + + @Test + public void givenListOfType_whenGetReturnRype_shouldCaptureTypeAtRuntime() throws NoSuchMethodException { + //given + Method getMethod = List.class.getMethod("get", int.class); + + //when + Invokable, ?> invokable = new TypeToken>() { + }.method(getMethod); + + //then + assertEquals(TypeToken.of(Integer.class), invokable.getReturnType()); // Not Object.class! + } + + + abstract class ParametrizedClass { + TypeToken type = new TypeToken(getClass()) { + }; + } + + class CustomClass { + public void somePublicMethod() { + } + + public final void notOverridablePublicMethod() { + + } + } +} diff --git a/guice-intro/pom.xml b/guice-intro/pom.xml new file mode 100644 index 0000000000..1f0d7679b7 --- /dev/null +++ b/guice-intro/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + com.baeldung.examples.guice + guice-intro + 1.0-SNAPSHOT + jar + + + com.google.inject + guice + ${guice.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + UTF-8 + 1.8 + 1.8 + 4.1.0 + + guice-intro + diff --git a/guice-intro/src/main/java/com/baeldung/examples/RunGuice.java b/guice-intro/src/main/java/com/baeldung/examples/RunGuice.java new file mode 100644 index 0000000000..b4b3e8571e --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/RunGuice.java @@ -0,0 +1,36 @@ + +package com.baeldung.examples; + +import com.baeldung.examples.guice.Communication; +import com.baeldung.examples.guice.binding.AOPModule; +import com.baeldung.examples.guice.modules.BasicModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import java.util.Scanner; + +/** + * + * @author Baeldung + */ +public class RunGuice { + + public static void main(String[] args) { + Injector injector = Guice.createInjector(new BasicModule(), new AOPModule()); + Communication comms = injector.getInstance(Communication.class); + Scanner scanner = new Scanner(System.in); + System.out.println("Enter your message to be sent; press Q to quit and P to print the message log"); + while (true) { + String input = scanner.nextLine(); + if (input.equalsIgnoreCase("q")) { + System.exit(0); + } + if (input.equalsIgnoreCase("p")) { + comms.print(); + } else { + comms.sendMessage(input); + } + + } + + } +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/Communication.java b/guice-intro/src/main/java/com/baeldung/examples/guice/Communication.java new file mode 100644 index 0000000000..c4b17b57d2 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/Communication.java @@ -0,0 +1,57 @@ + +package com.baeldung.examples.guice; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import java.util.Date; +import java.util.LinkedList; +import java.util.Queue; +import java.util.logging.Logger; + +/** + * + * @author Baeldung + */ +public class Communication { + + final Date start = new Date(); + + @Inject + private Logger logger; + + private Queue messageLog; + + @Named("CommsUUID") + private String commsID; + + @Inject + private DefaultCommunicator communicator; + + public Communication(Boolean keepRecords) { + if (keepRecords) { + messageLog = new LinkedList(); + } + } + + public boolean sendMessage(String message) { + if (!message.isEmpty() && messageLog != null) { + messageLog.add(message); + } + return communicator.sendMessage(message); + } + + public void print() { + if (messageLog != null) { + for (String message : messageLog) { + logger.info(message); + } + } else { + logger.info("Message logging wasn't enabled"); + } + } + + public DefaultCommunicator getCommunicator() { + return this.communicator; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/CommunicationMode.java b/guice-intro/src/main/java/com/baeldung/examples/guice/CommunicationMode.java new file mode 100644 index 0000000000..444b775478 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/CommunicationMode.java @@ -0,0 +1,12 @@ + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.constant.CommunicationModel; + +public interface CommunicationMode { + + public CommunicationModel getMode(); + + public boolean sendMessage(String message); + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java b/guice-intro/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java new file mode 100644 index 0000000000..423c24f789 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java @@ -0,0 +1,48 @@ + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.marker.Communicator; +import com.google.inject.Inject; +import com.google.inject.name.Named; + + +public class DefaultCommunicator implements Communicator { + + private CommunicationMode defaultCommsMode; + @Inject + @Named("SMSComms") + CommunicationMode smsCommsMode; + @Inject + @Named("EmailComms") + CommunicationMode emailCommsMode; + @Inject + @Named("IMComms") + CommunicationMode imCommsMode; + + protected DefaultCommunicator(CommunicationMode defaultComms) { + this.defaultCommsMode = defaultComms; + } + + public DefaultCommunicator() { + + } + + public boolean sendMessage(String message) { + boolean sent = false; + if (defaultCommsMode != null) { + sent = sendMessageByDefault(message); + } else { + sent = smsCommsMode.sendMessage(message); + } + return sent; + } + + private boolean sendMessageByDefault(String message) { + boolean sent = false; + if (message != null && !message.trim().equals("")) { + return defaultCommsMode.sendMessage(message); + } + return sent; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java b/guice-intro/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java new file mode 100644 index 0000000000..642ee7ace0 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java @@ -0,0 +1,23 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.baeldung.examples.guice.constant.CommunicationModel; + +/** + * + * @author Baekdung + */ +public class EmailCommunicationMode implements CommunicationMode { + + @Override + public CommunicationModel getMode() { + return CommunicationModel.EMAIL; + } + + @Override + @MessageSentLoggable + public boolean sendMessage(String Message) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java b/guice-intro/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java new file mode 100644 index 0000000000..9f34e9a241 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java @@ -0,0 +1,30 @@ + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.baeldung.examples.guice.constant.CommunicationModel; +import com.google.inject.Inject; +import java.util.logging.Logger; + +/** + * + * @author Baeldung + */ +public class IMCommunicationMode implements CommunicationMode { + + @Inject + private Logger logger; + + @Override + public CommunicationModel getMode() { + return CommunicationModel.IM; + } + + @Override + @MessageSentLoggable + public boolean sendMessage(String message) { + logger.info("IM Message Sent"); + return true; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java b/guice-intro/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java new file mode 100644 index 0000000000..251e249971 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java @@ -0,0 +1,29 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.baeldung.examples.guice.constant.CommunicationModel; +import com.google.inject.Inject; +import java.util.logging.Logger; + +/** + * + * @author Baeldung + */ +public class SMSCommunicationMode implements CommunicationMode { + + @Inject + private Logger logger; + + @Override + public CommunicationModel getMode() { + return CommunicationModel.SMS; + } + + @Override + @MessageSentLoggable + public boolean sendMessage(String message) { + logger.info("SMS message sent"); + return true; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java b/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java new file mode 100644 index 0000000000..8926dfa714 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java @@ -0,0 +1,22 @@ +package com.baeldung.examples.guice.aop; + +import java.util.logging.Logger; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * + * @author Baeldung + */ +public class MessageLogger implements MethodInterceptor { + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + Object[] objectArray = invocation.getArguments(); + int i = 0; + for (Object object : objectArray) { + Logger.getAnonymousLogger().info("Sending message: " + object.toString()); + } + return invocation.proceed(); + } +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java b/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java new file mode 100644 index 0000000000..cacf3bde7c --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java @@ -0,0 +1,16 @@ +package com.baeldung.examples.guice.aop; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author Baeldung + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface MessageSentLoggable { + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java b/guice-intro/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java new file mode 100644 index 0000000000..dc9d258efa --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java @@ -0,0 +1,22 @@ +package com.baeldung.examples.guice.binding; + +import com.baeldung.examples.guice.aop.MessageLogger; +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.google.inject.AbstractModule; +import com.google.inject.matcher.Matchers; + +/** + * + * @author Baeldung + */ +public class AOPModule extends AbstractModule { + + @Override + protected void configure() { + bindInterceptor(Matchers.any(), + Matchers.annotatedWith(MessageSentLoggable.class), + new MessageLogger() + ); + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java b/guice-intro/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java new file mode 100644 index 0000000000..9168195130 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java @@ -0,0 +1,36 @@ +package com.baeldung.examples.guice.binding; + +import com.baeldung.examples.guice.Communication; +import com.baeldung.examples.guice.CommunicationMode; +import com.baeldung.examples.guice.DefaultCommunicator; +import com.baeldung.examples.guice.EmailCommunicationMode; +import com.baeldung.examples.guice.IMCommunicationMode; +import com.baeldung.examples.guice.SMSCommunicationMode; +import com.google.inject.AbstractModule; +import com.google.inject.name.Names; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Baeldung + */ +public class BasicModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(Communication.class).toConstructor(Communication.class.getConstructor(Boolean.TYPE)); + } catch (NoSuchMethodException ex) { + Logger.getLogger(BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } + bind(DefaultCommunicator.class).annotatedWith(Names.named("AnotherCommunicator")).to(DefaultCommunicator.class).asEagerSingleton(); + + bind(CommunicationMode.class).annotatedWith(Names.named("IMComms")).to(IMCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("EmailComms")).to(EmailCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("SMSComms")).to(SMSCommunicationMode.class); + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java b/guice-intro/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java new file mode 100644 index 0000000000..b9fa604a32 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java @@ -0,0 +1,16 @@ +package com.baeldung.examples.guice.constant; + +/** + * + * @author Baeldung + */ +public enum CommunicationModel { + + EMAIL("Email"), SMS("SMS"), IM("IM"), PHONE("Phone"); + + final String name; + + CommunicationModel(String name) { + this.name = name; + } +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/marker/Communicator.java b/guice-intro/src/main/java/com/baeldung/examples/guice/marker/Communicator.java new file mode 100644 index 0000000000..239666b6ab --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/marker/Communicator.java @@ -0,0 +1,11 @@ +package com.baeldung.examples.guice.marker; + +/** + * + * @author Baeldung + */ +public interface Communicator { + + public boolean sendMessage(String message); + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java b/guice-intro/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java new file mode 100644 index 0000000000..47b3e2e573 --- /dev/null +++ b/guice-intro/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java @@ -0,0 +1,37 @@ +package com.baeldung.examples.guice.modules; + +import com.baeldung.examples.guice.Communication; +import com.baeldung.examples.guice.CommunicationMode; +import com.baeldung.examples.guice.DefaultCommunicator; +import com.baeldung.examples.guice.EmailCommunicationMode; +import com.baeldung.examples.guice.IMCommunicationMode; +import com.baeldung.examples.guice.SMSCommunicationMode; +import com.google.inject.AbstractModule; +import com.google.inject.name.Names; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Baeldung + */ +public class BasicModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(Communication.class).toConstructor(Communication.class.getConstructor(Boolean.class)); + bind(Boolean.class).toInstance(true); + } catch (NoSuchMethodException ex) { + Logger.getLogger(com.baeldung.examples.guice.binding.BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(com.baeldung.examples.guice.binding.BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } + bind(DefaultCommunicator.class).annotatedWith(Names.named("AnotherCommunicator")).to(DefaultCommunicator.class).asEagerSingleton(); + + bind(CommunicationMode.class).annotatedWith(Names.named("IMComms")).to(IMCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("EmailComms")).to(EmailCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("SMSComms")).to(SMSCommunicationMode.class); + } + +} diff --git a/hbase/pom.xml b/hbase/pom.xml new file mode 100644 index 0000000000..2382e47af2 --- /dev/null +++ b/hbase/pom.xml @@ -0,0 +1,51 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + hbase + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + org.apache.hbase + hbase-client + ${hbase.version} + + + org.apache.hbase + hbase + ${hbase.version} + + + junit + junit + ${junit.version} + test + + + + + 1.3.0 + 4.12 + + + + \ No newline at end of file diff --git a/hbase/src/main/java/org/baeldung/hbase/HBaseClientOperations.java b/hbase/src/main/java/org/baeldung/hbase/HBaseClientOperations.java new file mode 100644 index 0000000000..c78eacc834 --- /dev/null +++ b/hbase/src/main/java/org/baeldung/hbase/HBaseClientOperations.java @@ -0,0 +1,193 @@ +package org.baeldung.hbase; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.*; +import org.apache.hadoop.hbase.filter.*; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.FilterList.Operator; +import org.apache.hadoop.hbase.util.Bytes; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +public class HBaseClientOperations { + private final static byte[] cellData = Bytes.toBytes("cell_data"); + + /** + * Drop tables if this value is set true. + */ + static boolean INITIALIZE_AT_FIRST = true; + + /** + * + * + * Row1Family1:Qualifier1Family1:Qualifier2 + * + * + * Row2Family1:Qualifier1Family2:Qualifier3 + * + * + * Row3Family1:Qualifier1Family2:Qualifier3 + * + *
+ */ + private final TableName table1 = TableName.valueOf("Table1"); + private final String family1 = "Family1"; + private final String family2 = "Family2"; + + private final byte[] row1 = Bytes.toBytes("Row1"); + private final byte[] row2 = Bytes.toBytes("Row2"); + private final byte[] row3 = Bytes.toBytes("Row3"); + private final byte[] qualifier1 = Bytes.toBytes("Qualifier1"); + private final byte[] qualifier2 = Bytes.toBytes("Qualifier2"); + private final byte[] qualifier3 = Bytes.toBytes("Qualifier3"); + + private void createTable(Admin admin) throws IOException { + HTableDescriptor desc = new HTableDescriptor(table1); + desc.addFamily(new HColumnDescriptor(family1)); + desc.addFamily(new HColumnDescriptor(family2)); + admin.createTable(desc); + } + + private void delete(Table table) throws IOException { + final byte[] rowToBeDeleted = Bytes.toBytes("RowToBeDeleted"); + System.out.println("\n*** DELETE ~Insert data and then delete it~ ***"); + + System.out.println("Inserting a data to be deleted later."); + Put put = new Put(rowToBeDeleted); + put.addColumn(family1.getBytes(), qualifier1, cellData); + table.put(put); + + Get get = new Get(rowToBeDeleted); + Result result = table.get(get); + byte[] value = result.getValue(family1.getBytes(), qualifier1); + System.out.println("Fetch the data: " + Bytes.toString(value)); + assert Arrays.equals(cellData, value); + + System.out.println("Deleting"); + Delete delete = new Delete(rowToBeDeleted); + delete.addColumn(family1.getBytes(), qualifier1); + table.delete(delete); + + result = table.get(get); + value = result.getValue(family1.getBytes(), qualifier1); + System.out.println("Fetch the data: " + Bytes.toString(value)); + assert Arrays.equals(null, value); + + System.out.println("Done. "); + } + + private void deleteTable(Admin admin) throws IOException { + if (admin.tableExists(table1)) { + admin.disableTable(table1); + admin.deleteTable(table1); + } + } + + private void filters(Table table) throws IOException { + System.out.println("\n*** FILTERS ~ scanning with filters to fetch a row of which key is larget than \"Row1\"~ ***"); + Filter filter1 = new PrefixFilter(row1); + Filter filter2 = new QualifierFilter(CompareOp.GREATER_OR_EQUAL, new BinaryComparator( + qualifier1)); + + List filters = Arrays.asList(filter1, filter2); + + Scan scan = new Scan(); + scan.setFilter(new FilterList(Operator.MUST_PASS_ALL, filters)); + + try (ResultScanner scanner = table.getScanner(scan)) { + int i = 0; + for (Result result : scanner) { + System.out.println("Filter " + scan.getFilter() + " matched row: " + result); + i++; + } + assert i == 2 : "This filtering sample should return 1 row but was " + i + "."; + } + System.out.println("Done. "); + } + + private void get(Table table) throws IOException { + System.out.println("\n*** GET example ~fetching the data in Family1:Qualifier1~ ***"); + + Get g = new Get(row1); + Result r = table.get(g); + byte[] value = r.getValue(family1.getBytes(), qualifier1); + + System.out.println("Fetched value: " + Bytes.toString(value)); + assert Arrays.equals(cellData, value); + System.out.println("Done. "); + } + + private void put(Admin admin, Table table) throws IOException { + System.out.println("\n*** PUT example ~inserting \"cell-data\" into Family1:Qualifier1 of Table1 ~ ***"); + + // Row1 => Family1:Qualifier1, Family1:Qualifier2 + Put p = new Put(row1); + p.addImmutable(family1.getBytes(), qualifier1, cellData); + p.addImmutable(family1.getBytes(), qualifier2, cellData); + table.put(p); + + // Row2 => Family1:Qualifier1, Family2:Qualifier3 + p = new Put(row2); + p.addImmutable(family1.getBytes(), qualifier1, cellData); + p.addImmutable(family2.getBytes(), qualifier3, cellData); + table.put(p); + + // Row3 => Family1:Qualifier1, Family2:Qualifier3 + p = new Put(row3); + p.addImmutable(family1.getBytes(), qualifier1, cellData); + p.addImmutable(family2.getBytes(), qualifier3, cellData); + table.put(p); + + admin.disableTable(table1); + try { + HColumnDescriptor desc = new HColumnDescriptor(row1); + admin.addColumn(table1, desc); + System.out.println("Success."); + } catch (Exception e) { + System.out.println("Failed."); + System.out.println(e.getMessage()); + } finally { + admin.enableTable(table1); + } + System.out.println("Done. "); + } + + public void run(Configuration config) throws IOException { + try (Connection connection = ConnectionFactory.createConnection(config)) { + + Admin admin = connection.getAdmin(); + if (INITIALIZE_AT_FIRST) { + deleteTable(admin); + } + + if (!admin.tableExists(table1)) { + createTable(admin); + } + + Table table = connection.getTable(table1); + put(admin, table); + get(table); + scan(table); + filters(table); + delete(table); + } + } + + private void scan(Table table) throws IOException { + System.out.println("\n*** SCAN example ~fetching data in Family1:Qualifier1 ~ ***"); + + Scan scan = new Scan(); + scan.addColumn(family1.getBytes(), qualifier1); + + try (ResultScanner scanner = table.getScanner(scan)) { + for (Result result : scanner) + System.out.println("Found row: " + result); + } + System.out.println("Done."); + } +} \ No newline at end of file diff --git a/hbase/src/main/java/org/baeldung/hbase/HbaseClientExample.java b/hbase/src/main/java/org/baeldung/hbase/HbaseClientExample.java new file mode 100644 index 0000000000..07cb7df480 --- /dev/null +++ b/hbase/src/main/java/org/baeldung/hbase/HbaseClientExample.java @@ -0,0 +1,38 @@ +package org.baeldung.hbase; + + +import com.google.protobuf.ServiceException; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.MasterNotRunningException; +import org.apache.hadoop.hbase.client.HBaseAdmin; + +import java.io.IOException; + +//install hbase locally & hbase master start +public class HbaseClientExample { + + public static void main(String[] args) throws IOException, ServiceException { + new HbaseClientExample().connect(); + } + + private void connect() throws IOException, ServiceException { + Configuration config = HBaseConfiguration.create(); + + String path = this.getClass().getClassLoader().getResource("hbase-site.xml").getPath(); + + config.addResource(new Path(path)); + + try { + HBaseAdmin.checkHBaseAvailable(config); + } catch (MasterNotRunningException e) { + System.out.println("HBase is not running." + e.getMessage()); + return; + } + + HBaseClientOperations HBaseClientOperations = new HBaseClientOperations(); + HBaseClientOperations.run(config); + } + +} \ No newline at end of file diff --git a/hbase/src/main/resources/hbase-site.xml b/hbase/src/main/resources/hbase-site.xml new file mode 100644 index 0000000000..895529161c --- /dev/null +++ b/hbase/src/main/resources/hbase-site.xml @@ -0,0 +1,12 @@ + + + + + hbase.zookeeper.quorum + localhost + + + hbase.zookeeper.property.clientPort + 2181 + + \ No newline at end of file diff --git a/httpclient/README.md b/httpclient/README.md index a848edfea6..2a98c2feac 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -19,3 +19,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload) - [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) - [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) +- [Advanced HttpClient Configuration](http://www.baeldung.com/httpclient-advanced-config) diff --git a/jackson/README.md b/jackson/README.md index 67a03589a8..d9faa377f1 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -25,3 +25,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [More Jackson Annotations](http://www.baeldung.com/jackson-advanced-annotations) - [Inheritance with Jackson](http://www.baeldung.com/jackson-inheritance) - [Guide to @JsonFormat in Jackson](http://www.baeldung.com/jackson-jsonformat) +- [A Guide to Optional with Jackson](http://www.baeldung.com/jackson-optional) diff --git a/jasypt/pom.xml b/jasypt/pom.xml new file mode 100644 index 0000000000..7e0c51f0b9 --- /dev/null +++ b/jasypt/pom.xml @@ -0,0 +1,34 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + jasypt + + + + org.jasypt + jasypt + ${jasypt.version} + + + junit + junit + ${junit.version} + test + + + + + 1.9.2 + 4.12 + + + + \ No newline at end of file diff --git a/jasypt/src/test/java/org/baeldung/jasypt/JasyptTest.java b/jasypt/src/test/java/org/baeldung/jasypt/JasyptTest.java new file mode 100644 index 0000000000..c4bed5de83 --- /dev/null +++ b/jasypt/src/test/java/org/baeldung/jasypt/JasyptTest.java @@ -0,0 +1,98 @@ +package org.baeldung.jasypt; + + +import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; +import org.jasypt.util.password.BasicPasswordEncryptor; +import org.jasypt.util.text.BasicTextEncryptor; +import org.junit.Ignore; +import org.junit.Test; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotSame; +import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; + +public class JasyptTest { + + @Test + public void givenTextPassword_whenDecrypt_thenCompareToEncrypted() { + //given + BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); + String password = "secret-pass"; + textEncryptor.setPasswordCharArray("some-random-password".toCharArray()); + + //when + String myEncryptedText = textEncryptor.encrypt(password); + assertNotSame(password, myEncryptedText); //myEncryptedText can be save in db + + //then + String plainText = textEncryptor.decrypt(myEncryptedText); + assertEquals(plainText, password); + } + + @Test + public void givenTextPassword_whenOneWayEncryption_thenCompareEncryptedPasswordsShouldBeSame(){ + String password = "secret-pass"; + BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor(); + String encryptedPassword = passwordEncryptor.encryptPassword(password); + + //when + boolean result = passwordEncryptor.checkPassword("secret-pass", encryptedPassword); + + //then + assertTrue(result); + } + + @Test + public void givenTextPassword_whenOneWayEncryption_thenCompareEncryptedPasswordsShouldNotBeSame(){ + String password = "secret-pass"; + BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor(); + String encryptedPassword = passwordEncryptor.encryptPassword(password); + + //when + boolean result = passwordEncryptor.checkPassword("secret-pass-not-same", encryptedPassword); + + //then + assertFalse(result); + } + + + + @Test + @Ignore("should have installed local_policy.jar") + public void givenTextPassword_whenDecrypt_thenCompareToEncryptedWithCustomAlgorithm() { + //given + StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); + String password = "secret-pass"; + encryptor.setPassword("secret-pass"); + encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); + + //when + String encryptedText = encryptor.encrypt("secret-pass"); + assertNotSame(password, encryptedText); + + //then + String plainText = encryptor.decrypt(encryptedText); + assertEquals(plainText, password); + } + + @Test + @Ignore("should have installed local_policy.jar") + public void givenTextPassword_whenDecryptOnHighPerformance_thenDecrypt(){ + //given + String password = "secret-pass"; + PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); + encryptor.setPoolSize(4); + encryptor.setPassword(password); + encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); + + //when + String encryptedText = encryptor.encrypt(password); + assertNotSame(password, encryptedText); + + //then + String plainText = encryptor.decrypt(encryptedText); + assertEquals(plainText, password); + } +} diff --git a/java-mongodb/README.md b/java-mongodb/README.md new file mode 100644 index 0000000000..01245ac6cf --- /dev/null +++ b/java-mongodb/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb) diff --git a/java-websocket/pom.xml b/java-websocket/pom.xml new file mode 100644 index 0000000000..929e6491fd --- /dev/null +++ b/java-websocket/pom.xml @@ -0,0 +1,41 @@ + + 4.0.0 + com.baeldung + java-websocket + war + 0.0.1-SNAPSHOT + java-websocket Maven Webapp + http://maven.apache.org + + + UTF-8 + + + + + javax.websocket + javax.websocket-api + 1.1 + + + com.google.code.gson + gson + 2.8.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + diff --git a/java-websocket/src/main/java/com/baeldung/model/Message.java b/java-websocket/src/main/java/com/baeldung/model/Message.java new file mode 100644 index 0000000000..3d5bbcbc5d --- /dev/null +++ b/java-websocket/src/main/java/com/baeldung/model/Message.java @@ -0,0 +1,36 @@ +package com.baeldung.model; + +public class Message { + private String from; + private String to; + private String content; + + @Override + public String toString() { + return super.toString(); + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/java-websocket/src/main/java/com/baeldung/websocket/ChatEndpoint.java b/java-websocket/src/main/java/com/baeldung/websocket/ChatEndpoint.java new file mode 100644 index 0000000000..c4e20f4b27 --- /dev/null +++ b/java-websocket/src/main/java/com/baeldung/websocket/ChatEndpoint.java @@ -0,0 +1,71 @@ +package com.baeldung.websocket; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import javax.websocket.EncodeException; +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; + +import com.baeldung.model.Message; + +@ServerEndpoint(value = "/chat/{username}", decoders = MessageDecoder.class, encoders = MessageEncoder.class) +public class ChatEndpoint { + private Session session; + private static final Set chatEndpoints = new CopyOnWriteArraySet<>(); + private static HashMap users = new HashMap<>(); + + @OnOpen + public void onOpen(Session session, @PathParam("username") String username) throws IOException, EncodeException { + + this.session = session; + chatEndpoints.add(this); + users.put(session.getId(), username); + + Message message = new Message(); + message.setFrom(username); + message.setContent("Connected!"); + broadcast(message); + } + + @OnMessage + public void onMessage(Session session, Message message) throws IOException, EncodeException { + message.setFrom(users.get(session.getId())); + broadcast(message); + } + + @OnClose + public void onClose(Session session) throws IOException, EncodeException { + chatEndpoints.remove(this); + Message message = new Message(); + message.setFrom(users.get(session.getId())); + message.setContent("Disconnected!"); + broadcast(message); + } + + @OnError + public void onError(Session session, Throwable throwable) { + // Do error handling here + } + + private static void broadcast(Message message) throws IOException, EncodeException { + chatEndpoints.forEach(endpoint -> { + synchronized (endpoint) { + try { + endpoint.session.getBasicRemote() + .sendObject(message); + } catch (IOException | EncodeException e) { + e.printStackTrace(); + } + } + }); + } + +} diff --git a/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java b/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java new file mode 100644 index 0000000000..29ae5b93e6 --- /dev/null +++ b/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java @@ -0,0 +1,32 @@ +package com.baeldung.websocket; + +import javax.websocket.DecodeException; +import javax.websocket.Decoder; +import javax.websocket.EndpointConfig; + +import com.baeldung.model.Message; +import com.google.gson.Gson; + +public class MessageDecoder implements Decoder.Text { + @Override + public Message decode(String s) throws DecodeException { + Gson gson = new Gson(); + Message message = gson.fromJson(s, Message.class); + return message; + } + + @Override + public boolean willDecode(String s) { + return (s != null); + } + + @Override + public void init(EndpointConfig endpointConfig) { + // Custom initialization logic + } + + @Override + public void destroy() { + // Close resources + } +} diff --git a/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java b/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java new file mode 100644 index 0000000000..bfecc87a96 --- /dev/null +++ b/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java @@ -0,0 +1,27 @@ +package com.baeldung.websocket; + +import javax.websocket.EncodeException; +import javax.websocket.Encoder; +import javax.websocket.EndpointConfig; + +import com.baeldung.model.Message; +import com.google.gson.Gson; + +public class MessageEncoder implements Encoder.Text { + @Override + public String encode(Message message) throws EncodeException { + Gson gson = new Gson(); + String json = gson.toJson(message); + return json; + } + + @Override + public void init(EndpointConfig endpointConfig) { + // Custom initialization logic + } + + @Override + public void destroy() { + // Close resources + } +} diff --git a/java-websocket/src/main/webapp/WEB-INF/beans.xml b/java-websocket/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000..73cd0d8e10 --- /dev/null +++ b/java-websocket/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/java-websocket/src/main/webapp/WEB-INF/web.xml b/java-websocket/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..9f88c1f963 --- /dev/null +++ b/java-websocket/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/java-websocket/src/main/webapp/index.html b/java-websocket/src/main/webapp/index.html new file mode 100644 index 0000000000..2b76fb1e49 --- /dev/null +++ b/java-websocket/src/main/webapp/index.html @@ -0,0 +1,30 @@ + + + Chat + + + + + + + + + + + + + +
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/java-websocket/src/main/webapp/style.css b/java-websocket/src/main/webapp/style.css new file mode 100644 index 0000000000..ec0982005a --- /dev/null +++ b/java-websocket/src/main/webapp/style.css @@ -0,0 +1,136 @@ +body { + font-family: Arial, Helvetica, sans-serif; + font-size: 80%; + background-color: #1f1f1f; +} + +#wrapper { + width: 960px; + margin: auto; + text-align: left; + color: #d9d9d9; +} + +p { + text-align: left; +} + +.button { + display: inline; + color: #fff; + background-color: #f2791d; + padding: 8px; + margin: auto; + border-radius: 8px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + box-shadow: none; + border: none; +} + +.button:hover { + background-color: #ffb15e; +} +.button a, a:visited, a:hover, a:active { + color: #fff; + text-decoration: none; +} + +#addDevice { + text-align: center; + width: 960px; + margin: auto; + margin-bottom: 10px; +} + +#addDeviceForm { + text-align: left; + width: 400px; + margin: auto; + padding: 10px; +} + +#addDeviceForm span { + display: block; +} + +#content { + margin: auto; + width: 960px; +} + +.device { + width: 180px; + height: 110px; + margin: 10px; + padding: 16px; + color: #fff; + vertical-align: top; + border-radius: 8px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + display: inline-block; +} + +.device.off { + background-color: #c8cccf; +} + +.device span { + display: block; +} + +.deviceName { + text-align: center; + font-weight: bold; + margin-bottom: 12px; +} + +.removeDevice { + margin-top: 12px; + text-align: center; +} + +.device.Appliance { + background-color: #5eb85e; +} + +.device.Appliance a:hover { + color: #a1ed82; +} + +.device.Electronics { + background-color: #0f90d1; +} + +.device.Electronics a:hover { + color: #4badd1; +} + +.device.Lights { + background-color: #c2a00c; +} + +.device.Lights a:hover { + color: #fad232; +} + +.device.Other { + background-color: #db524d; +} + +.device.Other a:hover { + color: #ff907d; +} + +.device a { + text-decoration: none; +} + +.device a:visited, a:active, a:hover { + color: #fff; +} + +.device a:hover { + text-decoration: underline; +} \ No newline at end of file diff --git a/java-websocket/src/main/webapp/websocket.js b/java-websocket/src/main/webapp/websocket.js new file mode 100644 index 0000000000..39e5687f0c --- /dev/null +++ b/java-websocket/src/main/webapp/websocket.js @@ -0,0 +1,23 @@ +var ws; + +function connect() { + var username = document.getElementById("username").value; + ws = new WebSocket("ws://" + document.location.host + "/java-websocket/chat/" + username); + + + ws.onmessage = function(event) { + var log = document.getElementById("log"); + console.log(event.data); + var message = JSON.parse(event.data); + log.innerHTML += message.from + " : " + message.content + "\n"; + }; +} + +function send() { + var content = document.getElementById("msg").value; + var json = JSON.stringify({ + "content":content + }); + + ws.send(json); +} \ No newline at end of file diff --git a/javaslang/README.md b/javaslang/README.md index 334ac02f60..e451883516 100644 --- a/javaslang/README.md +++ b/javaslang/README.md @@ -1,2 +1,4 @@ ### Relevant Articles: - [Introduction to Javaslang](http://www.baeldung.com/javaslang) +- [Guide to Try in Javaslang](http://www.baeldung.com/javaslang-try) +- [Guide to Pattern Matching in Javaslang](http://www.baeldung.com/javaslang-pattern-matching) diff --git a/jee7/README.md b/jee7/README.md index 44ca9c2f6e..bc242c3340 100644 --- a/jee7/README.md +++ b/jee7/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Scheduling in Java EE](http://www.baeldung.com/scheduling-in-java-enterprise-edition) +- [JSON Processing in Java EE 7](http://www.baeldung.com/jee7-json) diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java new file mode 100644 index 0000000000..e3f1667595 --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java @@ -0,0 +1,57 @@ +package com.baeldung.javaeeannotations; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.annotation.HttpConstraint; +import javax.servlet.annotation.HttpMethodConstraint; +import javax.servlet.annotation.ServletSecurity; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet( + name = "BankAccountServlet", + description = "Represents a Bank Account and it's transactions", + urlPatterns = {"/account", "/bankAccount" }, + initParams = { @WebInitParam(name = "type", value = "savings") } + ) +@ServletSecurity( + value = @HttpConstraint(rolesAllowed = {"admin"}), + httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"admin"})} + ) +public class AccountServlet extends javax.servlet.http.HttpServlet { + + String accountType = null; + + @Override + public void init(ServletConfig config) throws ServletException { + accountType = config.getInitParameter("type"); + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + PrintWriter writer = response.getWriter(); + writer.println("Hello, I am an AccountServlet!"); + writer.flush(); + } + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + double accountBalance = 1000d; + double interestRate = Double.parseDouble(request.getAttribute("interest").toString()); + + String paramDepositAmt = request.getParameter("dep"); + double depositAmt = Double.parseDouble(paramDepositAmt); + + accountBalance = accountBalance + depositAmt; + + PrintWriter writer = response.getWriter(); + writer.println(" Balance of " + accountType + " account is: " + + accountBalance + "
This account bares an interest rate of " + interestRate + + " % "); + writer.flush(); + + } +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java b/jee7/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java new file mode 100644 index 0000000000..6b43dd8a84 --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java @@ -0,0 +1,17 @@ +package com.baeldung.javaeeannotations; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class BankAppServletContextListener implements ServletContextListener { + + public void contextInitialized(ServletContextEvent sce) { + sce.getServletContext().setAttribute("ATTR_DEFAULT_LANGUAGE", "english"); + } + + public void contextDestroyed(ServletContextEvent sce) { + System.out.println("CONTEXT DESTROYED"); + } +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java b/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java new file mode 100644 index 0000000000..97de5ec0de --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java @@ -0,0 +1,36 @@ +package com.baeldung.javaeeannotations; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebFilter( + urlPatterns = "/bankAccount/*", + filterName = "LoggingFilter", + description = "Filter all account transaction URLs" + ) +public class LoggingFilter implements javax.servlet.Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + + res.sendRedirect(req.getContextPath() + "/login.jsp"); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java new file mode 100644 index 0000000000..8a6c709b81 --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java @@ -0,0 +1,29 @@ +package com.baeldung.javaeeannotations; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; + +@WebServlet(urlPatterns = { "/uploadCustDocs" }) +@MultipartConfig( + fileSizeThreshold = 1024 * 1024 * 20, + maxFileSize = 1024 * 1024 * 20, + maxRequestSize = 1024 * 1024 * 25, + location = "D:/custDocs" + ) +public class UploadCustomerDocumentsServlet extends HttpServlet { + + protected void doPost( + HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + for (Part part : request.getParts()) { + part.write("myFile"); + } + } + +} diff --git a/jee7/src/main/webapp/WEB-INF/web.xml b/jee7/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..0a3d84d2d4 --- /dev/null +++ b/jee7/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,11 @@ + + + + BASIC + default + + + \ No newline at end of file diff --git a/jee7/src/main/webapp/index.jsp b/jee7/src/main/webapp/index.jsp new file mode 100644 index 0000000000..0c389ef5b1 --- /dev/null +++ b/jee7/src/main/webapp/index.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +My Account + + +
+ Width: +    + +
+ + \ No newline at end of file diff --git a/jee7/src/main/webapp/login.jsp b/jee7/src/main/webapp/login.jsp new file mode 100644 index 0000000000..885df0c3d9 --- /dev/null +++ b/jee7/src/main/webapp/login.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Login + + +Login Here... + + \ No newline at end of file diff --git a/jee7/src/main/webapp/upload.jsp b/jee7/src/main/webapp/upload.jsp new file mode 100644 index 0000000000..020483b99f --- /dev/null +++ b/jee7/src/main/webapp/upload.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Insert title here + + +
+ +
+ +
+ + \ No newline at end of file diff --git a/jooq/pom.xml b/jooq/pom.xml new file mode 100644 index 0000000000..ef287d0292 --- /dev/null +++ b/jooq/pom.xml @@ -0,0 +1,46 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + jooq + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + org.jooq + jool + ${jool.version} + + + junit + junit + ${junit.version} + test + + + + + 0.9.12 + 4.12 + + + + \ No newline at end of file diff --git a/jooq/src/test/java/com/baeldung/JOOLTest.java b/jooq/src/test/java/com/baeldung/JOOLTest.java new file mode 100644 index 0000000000..13bf1a3ec3 --- /dev/null +++ b/jooq/src/test/java/com/baeldung/JOOLTest.java @@ -0,0 +1,243 @@ +package com.baeldung; + + +import junit.framework.Assert; +import org.jooq.lambda.Seq; +import org.jooq.lambda.Unchecked; +import org.jooq.lambda.function.Function1; +import org.jooq.lambda.function.Function2; +import org.jooq.lambda.tuple.Tuple; +import org.jooq.lambda.tuple.Tuple2; +import org.jooq.lambda.tuple.Tuple3; +import org.jooq.lambda.tuple.Tuple4; +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 junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; +import static org.jooq.lambda.tuple.Tuple.tuple; + +public class JOOLTest { + @Test + public void givenSeq_whenCheckContains_shouldReturnTrue() { + List concat = Seq.of(1, 2, 3).concat(Seq.of(4, 5, 6)).toList(); + + assertEquals(concat, Arrays.asList(1, 2, 3, 4, 5, 6)); + + + assertTrue(Seq.of(1, 2, 3, 4).contains(2)); + + + assertTrue(Seq.of(1, 2, 3, 4).containsAll(2, 3)); + + + assertTrue(Seq.of(1, 2, 3, 4).containsAny(2, 5)); + } + + @Test + public void givenStreams_whenJoin_shouldHaveElementsFromTwoStreams() { + //given + Stream left = Stream.of(1, 2, 4); + Stream right = Stream.of(1, 2, 3); + + //when + List rightCollected = right.collect(Collectors.toList()); + List collect = left.filter(rightCollected::contains).collect(Collectors.toList()); + + //then + assertEquals(collect, Arrays.asList(1, 2)); + } + + @Test + public void givenSeq_whenJoin_shouldHaveElementsFromBothSeq() { + assertEquals( + Seq.of(1, 2, 4).innerJoin(Seq.of(1, 2, 3), (a, b) -> a == b).toList(), + Arrays.asList(tuple(1, 1), tuple(2, 2)) + ); + + + assertEquals( + Seq.of(1, 2, 4).leftOuterJoin(Seq.of(1, 2, 3), (a, b) -> a == b).toList(), + Arrays.asList(tuple(1, 1), tuple(2, 2), tuple(4, null)) + ); + + assertEquals( + Seq.of(1, 2, 4).rightOuterJoin(Seq.of(1, 2, 3), (a, b) -> a == b).toList(), + Arrays.asList(tuple(1, 1), tuple(2, 2), tuple(null, 3)) + ); + + assertEquals( + Seq.of(1, 2).crossJoin(Seq.of("A", "B")).toList(), + Arrays.asList(tuple(1, "A"), tuple(1, "B"), tuple(2, "A"), tuple(2, "B")) + ); + } + + @Test + public void givenSeq_whenManipulateSeq_seqShouldHaveNewElementsInIt() { + assertEquals( + Seq.of(1, 2, 3).cycle().limit(9).toList(), + Arrays.asList(1, 2, 3, 1, 2, 3, 1, 2, 3) + ); + + assertEquals( + Seq.of(1, 2, 3).duplicate().map((first, second) -> tuple(first.toList(), second.toList())), + tuple(Arrays.asList(1, 2, 3), Arrays.asList(1, 2, 3)) + ); + + assertEquals( + Seq.of(1, 2, 3, 4).intersperse(0).toList(), + Arrays.asList(1, 0, 2, 0, 3, 0, 4) + ); + + assertEquals( + Seq.of(1, 2, 3, 4, 5).shuffle().toList().size(), + 5 + ); + + assertEquals( + Seq.of(1, 2, 3, 4).partition(i -> i > 2).map((first, second) -> tuple(first.toList(), second.toList())), + tuple(Arrays.asList(3, 4), Arrays.asList(1, 2)) + + ); + + assertEquals( + Seq.of(1, 2, 3, 4).reverse().toList(), + Arrays.asList(4, 3, 2, 1) + ); + } + + @Test + public void givenSeq_whenGroupByAndFold_shouldReturnProperSeq() { + + Map> expectedAfterGroupBy = new HashMap<>(); + expectedAfterGroupBy.put(1, Arrays.asList(1, 3)); + expectedAfterGroupBy.put(0, Arrays.asList(2, 4)); + + assertEquals( + Seq.of(1, 2, 3, 4).groupBy(i -> i % 2), + expectedAfterGroupBy + ); + + + assertEquals( + Seq.of("a", "b", "c").foldLeft("!", (u, t) -> u + t), + "!abc" + ); + + + assertEquals( + Seq.of("a", "b", "c").foldRight("!", (t, u) -> t + u), + "abc!" + ); + } + + @Test + public void givenSeq_whenUsingSeqWhile_shouldBehaveAsWhileLoop() { + + assertEquals( + Seq.of(1, 2, 3, 4, 5).skipWhile(i -> i < 3).toList(), + Arrays.asList(3, 4, 5) + ); + + assertEquals( + Seq.of(1, 2, 3, 4, 5).skipUntil(i -> i == 3).toList(), + Arrays.asList(3, 4, 5) + ); + } + + @Test + public void givenSeq_whenZip_shouldHaveZippedSeq() { + + assertEquals( + Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c")).toList(), + Arrays.asList(tuple(1, "a"), tuple(2, "b"), tuple(3, "c")) + ); + + assertEquals( + Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c"), (x, y) -> x + ":" + y).toList(), + Arrays.asList("1:a", "2:b", "3:c") + ); + + + assertEquals( + Seq.of("a", "b", "c").zipWithIndex().toList(), + Arrays.asList(tuple("a", 0L), tuple("b", 1L), tuple("c", 2L)) + ); + } + + + public Integer methodThatThrowsChecked(String arg) throws Exception { + return arg.length(); + } + + @Test + public void givenOperationThatThrowsCheckedException_whenExecuteAndNeedToWrapCheckedIntoUnchecked_shouldPass() { + //when + List collect = Stream.of("a", "b", "c").map(elem -> { + try { + return methodThatThrowsChecked(elem); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + }).collect(Collectors.toList()); + + //then + assertEquals( + collect, + Arrays.asList(1, 1, 1) + ); + } + + + @Test + public void givenOperationThatThrowsCheckedException_whenExecuteUsingUncheckedFuction_shouldPass() { + //when + List collect = Stream.of("a", "b", "c") + .map(Unchecked.function(elem -> methodThatThrowsChecked(elem))) + .collect(Collectors.toList()); + + //then + assertEquals( + collect, + Arrays.asList(1, 1, 1) + ); + } + + @Test + public void givenFunction_whenAppliedPartially_shouldAddNumberToPartialArgument() { + //given + Function2 addTwoNumbers = (v1, v2) -> v1 + v2; + addTwoNumbers.toBiFunction(); + Function1 addToTwo = addTwoNumbers.applyPartially(2); + + //when + Integer result = addToTwo.apply(5); + + //then + assertEquals(result, (Integer) 7); + } + + @Test + public void givenSeqOfTuples_whenTransformToLowerNumberOfTuples_shouldHaveProperResult() { + //given + Seq> personDetails = Seq.of(tuple("michael", "similar", 49), tuple("jodie", "variable", 43)); + Tuple2 tuple = tuple("winter", "summer"); + + //when + List> result = personDetails.map(t -> t.limit2().concat(tuple)).toList(); + + //then + assertEquals( + result, + Arrays.asList(tuple("michael", "similar", "winter", "summer"), tuple("jodie", "variable", "winter", "summer")) + ); + } + +} diff --git a/kotlin/README.md b/kotlin/README.md new file mode 100644 index 0000000000..6447a26f5c --- /dev/null +++ b/kotlin/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to the Kotlin Language](http://www.baeldung.com/kotlin) diff --git a/kotlin/src/main/kotlin/com/baeldung/kotlin/WhenBlockTypes.kt b/kotlin/src/main/kotlin/com/baeldung/kotlin/WhenBlockTypes.kt new file mode 100644 index 0000000000..6180da10d9 --- /dev/null +++ b/kotlin/src/main/kotlin/com/baeldung/kotlin/WhenBlockTypes.kt @@ -0,0 +1,28 @@ +package com.baeldung.kotlin + +enum class UnixFileType { + D, HYPHEN_MINUS, L +} + +sealed class UnixFile { + + abstract fun getFileType(): UnixFileType + + class RegularFile(val content: String) : UnixFile() { + override fun getFileType(): UnixFileType { + return UnixFileType.HYPHEN_MINUS + } + } + + class Directory(val children: List) : UnixFile() { + override fun getFileType(): UnixFileType { + return UnixFileType.D + } + } + + class SymbolicLink(val originalFile: UnixFile) : UnixFile() { + override fun getFileType(): UnixFileType { + return UnixFileType.L + } + } +} \ No newline at end of file diff --git a/kotlin/src/test/kotlin/com/baeldung/kotlin/WhenBlockUnitTest.kt b/kotlin/src/test/kotlin/com/baeldung/kotlin/WhenBlockUnitTest.kt new file mode 100644 index 0000000000..aa1891fa46 --- /dev/null +++ b/kotlin/src/test/kotlin/com/baeldung/kotlin/WhenBlockUnitTest.kt @@ -0,0 +1,136 @@ +package com.baeldung.kotlin + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class WhenBlockUnitTest { + + @Test + fun testWhenExpression() { + val directoryType = UnixFileType.D + + val objectType = when (directoryType) { + UnixFileType.D -> "d" + UnixFileType.HYPHEN_MINUS -> "-" + UnixFileType.L -> "l" + } + + assertEquals("d", objectType) + } + + @Test + fun testWhenExpressionWithDefaultCase() { + val fileType = UnixFileType.L + + val result = when (fileType) { + UnixFileType.L -> "linking to another file" + else -> "not a link" + } + + assertEquals("linking to another file", result) + } + + @Test(expected = IllegalArgumentException::class) + fun testWhenExpressionWithThrowException() { + val fileType = UnixFileType.L + + val result: Boolean = when (fileType) { + UnixFileType.HYPHEN_MINUS -> true + else -> throw IllegalArgumentException("Wrong type of file") + } + } + + @Test + fun testWhenStatement() { + val fileType = UnixFileType.HYPHEN_MINUS + + when (fileType) { + UnixFileType.HYPHEN_MINUS -> println("Regular file type") + UnixFileType.D -> println("Directory file type") + } + } + + @Test + fun testCaseCombination() { + val fileType = UnixFileType.D + + val frequentFileType: Boolean = when (fileType) { + UnixFileType.HYPHEN_MINUS, UnixFileType.D -> true + else -> false + } + + assertTrue(frequentFileType) + } + + @Test + fun testWhenWithoutArgument() { + val fileType = UnixFileType.L + + val objectType = when { + fileType === UnixFileType.L -> "l" + fileType === UnixFileType.HYPHEN_MINUS -> "-" + fileType === UnixFileType.D -> "d" + else -> "unknown file type" + } + + assertEquals("l", objectType) + } + + @Test + fun testDynamicCaseExpression() { + val unixFile = UnixFile.SymbolicLink(UnixFile.RegularFile("Content")) + + when { + unixFile.getFileType() == UnixFileType.D -> println("It's a directory!") + unixFile.getFileType() == UnixFileType.HYPHEN_MINUS -> println("It's a regular file!") + unixFile.getFileType() == UnixFileType.L -> println("It's a soft link!") + } + } + + @Test + fun testCollectionCaseExpressions() { + val regularFile = UnixFile.RegularFile("Test Content") + val symbolicLink = UnixFile.SymbolicLink(regularFile) + val directory = UnixFile.Directory(listOf(regularFile, symbolicLink)) + + val isRegularFileInDirectory = when (regularFile) { + in directory.children -> true + else -> false + } + + val isSymbolicLinkInDirectory = when { + symbolicLink in directory.children -> true + else -> false + } + + assertTrue(isRegularFileInDirectory) + assertTrue(isSymbolicLinkInDirectory) + } + + @Test + fun testRangeCaseExpressions() { + val fileType = UnixFileType.HYPHEN_MINUS + + val isCorrectType = when (fileType) { + in UnixFileType.D..UnixFileType.L -> true + else -> false + } + + assertTrue(isCorrectType) + } + + @Test + fun testWhenWithIsOperatorWithSmartCase() { + val unixFile: UnixFile = UnixFile.RegularFile("Test Content") + + val result = when (unixFile) { + is UnixFile.RegularFile -> unixFile.content + is UnixFile.Directory -> unixFile.children.map { it.getFileType() }.joinToString(", ") + is UnixFile.SymbolicLink -> unixFile.originalFile.getFileType() + } + + assertEquals("Test Content", result) + } + +} \ No newline at end of file diff --git a/libraries/pom.xml b/libraries/pom.xml new file mode 100644 index 0000000000..ee93ee934f --- /dev/null +++ b/libraries/pom.xml @@ -0,0 +1,48 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + libraries + libraries + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + + cglib + cglib + ${cglib.version} + + + junit + junit + ${junit.version} + test + + + + + 3.2.4 + 4.12 + + + + \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Class1.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Class1.java new file mode 100644 index 0000000000..fa0cba5b78 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Class1.java @@ -0,0 +1,8 @@ +package com.baeldung.cglib.mixin; + +public class Class1 implements Interface1 { + @Override + public String first() { + return "first behaviour"; + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Class2.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Class2.java new file mode 100644 index 0000000000..0db0620ab8 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Class2.java @@ -0,0 +1,8 @@ +package com.baeldung.cglib.mixin; + +public class Class2 implements Interface2 { + @Override + public String second() { + return "second behaviour"; + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Interface1.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface1.java new file mode 100644 index 0000000000..56ad679cad --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface1.java @@ -0,0 +1,5 @@ +package com.baeldung.cglib.mixin; + +public interface Interface1 { + String first(); +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Interface2.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface2.java new file mode 100644 index 0000000000..0dfb8737ab --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface2.java @@ -0,0 +1,5 @@ +package com.baeldung.cglib.mixin; + +public interface Interface2 { + String second(); +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/MixinInterface.java b/libraries/src/main/java/com/baeldung/cglib/mixin/MixinInterface.java new file mode 100644 index 0000000000..e7ed362a25 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/MixinInterface.java @@ -0,0 +1,4 @@ +package com.baeldung.cglib.mixin; + +public interface MixinInterface extends Interface1, Interface2 { +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/proxy/PersonService.java b/libraries/src/main/java/com/baeldung/cglib/proxy/PersonService.java new file mode 100644 index 0000000000..9085e6c49a --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/proxy/PersonService.java @@ -0,0 +1,11 @@ +package com.baeldung.cglib.proxy; + +public class PersonService { + public String sayHello(String name) { + return "Hello " + name; + } + + public Integer lengthOfName(String name) { + return name.length(); + } +} \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/BeanGeneratorTest.java b/libraries/src/test/java/com/baeldung/cglib/proxy/BeanGeneratorTest.java new file mode 100644 index 0000000000..1e49536065 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/BeanGeneratorTest.java @@ -0,0 +1,32 @@ +package com.baeldung.cglib.proxy; + + +import net.sf.cglib.beans.BeanGenerator; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static junit.framework.TestCase.assertEquals; + +public class BeanGeneratorTest { + + @Test + public void givenBeanCreator_whenAddProperty_thenClassShouldHaveFieldValue() throws Exception { + //given + BeanGenerator beanGenerator = new BeanGenerator(); + + //when + beanGenerator.addProperty("name", String.class); + Object myBean = beanGenerator.create(); + Method setter = myBean + .getClass() + .getMethod("setName", String.class); + setter.invoke(myBean, "some string value set by a cglib"); + + //then + Method getter = myBean + .getClass() + .getMethod("getName"); + assertEquals("some string value set by a cglib", getter.invoke(myBean)); + } +} diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/MixinTest.java b/libraries/src/test/java/com/baeldung/cglib/proxy/MixinTest.java new file mode 100644 index 0000000000..db8453e6c1 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/MixinTest.java @@ -0,0 +1,24 @@ +package com.baeldung.cglib.proxy; + +import com.baeldung.cglib.mixin.*; +import net.sf.cglib.proxy.Mixin; +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +public class MixinTest { + + @Test + public void givenTwoClasses_whenMixedIntoOne_thenMixinShouldHaveMethodsFromBothClasses() throws Exception { + //when + Mixin mixin = Mixin.create( + new Class[]{Interface1.class, Interface2.class, MixinInterface.class}, + new Object[]{new Class1(), new Class2()} + ); + MixinInterface mixinDelegate = (MixinInterface) mixin; + + //then + assertEquals("first behaviour", mixinDelegate.first()); + assertEquals("second behaviour", mixinDelegate.second()); + } +} diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/ProxyTest.java b/libraries/src/test/java/com/baeldung/cglib/proxy/ProxyTest.java new file mode 100644 index 0000000000..195c4b903d --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/ProxyTest.java @@ -0,0 +1,60 @@ +package com.baeldung.cglib.proxy; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.FixedValue; +import net.sf.cglib.proxy.MethodInterceptor; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ProxyTest { + @Test + public void givenPersonService_whenSayHello_thenReturnResult() { + //given + PersonService personService = new PersonService(); + + //when + String res = personService.sayHello("Tom"); + + //then + assertEquals(res, "Hello Tom"); + } + + @Test + public void givenEnhancerProxy_whenExtendPersonService_thenInterceptMethod() throws Exception { + //given + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(PersonService.class); + enhancer.setCallback((FixedValue) () -> "Hello Tom!"); + PersonService proxy = (PersonService) enhancer.create(); + + //when + String res = proxy.sayHello(null); + + //then + assertEquals("Hello Tom!", res); + } + + @Test + public void givenEnhancer_whenExecuteMethodOnProxy_thenInterceptOnlyStringReturnTypeMethod() throws Exception { + //given + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(PersonService.class); + enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> { + if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) { + return "Hello Tom!"; + } else { + return proxy.invokeSuper(obj, args); + } + }); + + //when + PersonService proxy = (PersonService) enhancer.create(); + + //then + assertEquals("Hello Tom!", proxy.sayHello(null)); + int lengthOfName = proxy.lengthOfName("Mary"); + assertEquals(4, lengthOfName); + } + +} \ No newline at end of file diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java index d88a967562..333b4f5e78 100644 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java +++ b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java @@ -6,6 +6,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.sql.Connection; import java.sql.ResultSet; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; @@ -25,83 +26,90 @@ public class CustomLoggingTest { public static void setup() throws Exception { Connection connection = ConnectionFactory.getConnection(); connection.createStatement() - .execute("CREATE TABLE logs(" + "when TIMESTAMP," + "logger VARCHAR(255)," + "level VARCHAR(255)," + "message VARCHAR(4096)," + "throwable TEXT)"); + .execute("CREATE TABLE logs(" + "when TIMESTAMP," + "logger VARCHAR(255)," + "level VARCHAR(255)," + "message VARCHAR(4096)," + "throwable TEXT)"); connection.commit(); } @Test - public void givenLoggerWithDefaultConfig_shouldLogToConsole() throws Exception { + public void givenLoggerWithDefaultConfig_whenLogToConsole_thanOK() throws Exception { Logger logger = LogManager.getLogger(getClass()); Exception e = new RuntimeException("This is only a test!"); + logger.info("This is a simple message at INFO level. " + "It will be hidden."); logger.error("This is a simple message at ERROR level. " + "This is the minimum visible level.", e); } @Test - public void givenLoggerWithConsoleConfig_shouldLogToConsoleInColors() throws Exception { + public void givenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK() throws Exception { Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER"); + Exception e = new RuntimeException("This is only a test!"); + logger.trace("This is a colored message at TRACE level."); logger.debug("This is a colored message at DEBUG level. " + "This is the minimum visible level."); logger.info("This is a colored message at INFO level."); logger.warn("This is a colored message at WARN level."); - Exception e = new RuntimeException("This is only a test!"); logger.error("This is a colored message at ERROR level.", e); logger.fatal("This is a colored message at FATAL level."); } @Test - public void givenLoggerWithConsoleConfig_shouldFilterByMarker() throws Exception { + public void givenLoggerWithConsoleConfig_whenFilterByMarker_thanOK() throws Exception { Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER"); Marker appError = MarkerManager.getMarker("APP_ERROR"); - logger.error(appError, "This marker message at ERROR level should be hidden."); Marker connectionTrace = MarkerManager.getMarker("CONN_TRACE"); + + logger.error(appError, "This marker message at ERROR level should be hidden."); logger.trace(connectionTrace, "This is a marker message at TRACE level."); } @Test - public void givenLoggerWithConsoleConfig_shouldFilterByThreadContext() throws Exception { + public void givenLoggerWithConsoleConfig_whenFilterByThreadContext_thanOK() throws Exception { Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT"); ThreadContext.put("userId", "1000"); logger.info("This is a log-visible user login. Maybe from an admin account?"); ThreadContext.put("userId", "1001"); logger.info("This is a log-invisible user login."); - } @Test - public void givenLoggerWithAsyncConfig_shouldLogToJsonFile() throws Exception { + public void givenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK() throws Exception { Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER"); + final int count = 88; for (int i = 0; i < count; i++) { logger.info("This is async JSON message #{} at INFO level.", count); } + long logEventsCount = Files.lines(Paths.get("target/logfile.json")) - .count(); + .count(); assertTrue(logEventsCount > 0 && logEventsCount <= count); } @Test - public void givenLoggerWithFailoverConfig_shouldLog() throws Exception { + public void givenLoggerWithFailoverConfig_whenLog_thanOK() throws Exception { Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER"); + Exception e = new RuntimeException("This is only a test!"); + logger.trace("This is a syslog message at TRACE level."); logger.debug("This is a syslog message at DEBUG level."); logger.info("This is a syslog message at INFO level. This is the minimum visible level."); logger.warn("This is a syslog message at WARN level."); - Exception e = new RuntimeException("This is only a test!"); logger.error("This is a syslog message at ERROR level.", e); logger.fatal("This is a syslog message at FATAL level."); } @Test - public void givenLoggerWithJdbcConfig_shouldLogToDataSource() throws Exception { + public void givenLoggerWithJdbcConfig_whenLogToDataSource_thanOK() throws Exception { Logger logger = LogManager.getLogger("JDBC_APPENDER"); + final int count = 88; for (int i = 0; i < count; i++) { logger.info("This is JDBC message #{} at INFO level.", count); } Connection connection = ConnectionFactory.getConnection(); ResultSet resultSet = connection.createStatement() - .executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs"); + .executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs"); + int logCount = 0; if (resultSet.next()) { logCount = resultSet.getInt("ROW_COUNT"); @@ -110,8 +118,9 @@ public class CustomLoggingTest { } @Test - public void givenLoggerWithRollingFileConfig_shouldLogToXMLFile() throws Exception { + public void givenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK() throws Exception { Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER"); + final int count = 88; for (int i = 0; i < count; i++) { logger.info("This is rolling file XML message #{} at INFO level.", i); diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/jdbc/ConnectionFactory.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/jdbc/ConnectionFactory.java index cc594f293c..73b323f335 100644 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/jdbc/ConnectionFactory.java +++ b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/jdbc/ConnectionFactory.java @@ -2,6 +2,7 @@ package com.baeldung.logging.log4j2.tests.jdbc; import org.apache.commons.dbcp2.BasicDataSource; import org.h2.Driver; + import java.sql.Connection; import java.sql.SQLException; diff --git a/log4j2/src/test/resources/log4j2.xml b/log4j2/src/test/resources/log4j2.xml index 83c1184f1f..21fd1da446 100644 --- a/log4j2/src/test/resources/log4j2.xml +++ b/log4j2/src/test/resources/log4j2.xml @@ -19,12 +19,14 @@ - + @@ -53,9 +55,11 @@ + diff --git a/metrics/README.md b/metrics/README.md new file mode 100644 index 0000000000..c98024c479 --- /dev/null +++ b/metrics/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Intro to Dropwizard Metrics](http://www.baeldung.com/dropwizard-metrics) diff --git a/mockito2/.gitignore b/mockito2/.gitignore new file mode 100644 index 0000000000..7f300600e6 --- /dev/null +++ b/mockito2/.gitignore @@ -0,0 +1,14 @@ +*.class + +.settings +.project + +#folders# +/target +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear diff --git a/mockito2/README.md b/mockito2/README.md new file mode 100644 index 0000000000..587f1341bb --- /dev/null +++ b/mockito2/README.md @@ -0,0 +1,5 @@ +========= + +## Mockito 2 and Java 8 Tips + +Examples on how to leverage Java 8 new features with Mockito version 2 diff --git a/mockito2/pom.xml b/mockito2/pom.xml new file mode 100644 index 0000000000..e116647009 --- /dev/null +++ b/mockito2/pom.xml @@ -0,0 +1,98 @@ + + + 4.0.0 + com.baeldung + mockito2 + 0.0.1-SNAPSHOT + jar + mockito-2-with-java8 + + + + + junit + junit + ${junit.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + + + **/*IntegrationTest.java + + + + + + + json + + + + + + + + + + UTF-8 + + + 4.12 + 2.7.5 + + + 3.6.0 + 2.19.1 + + diff --git a/mockito2/src/main/java/com/baeldung/mockito/java8/JobPosition.java b/mockito2/src/main/java/com/baeldung/mockito/java8/JobPosition.java new file mode 100644 index 0000000000..c7712fa47e --- /dev/null +++ b/mockito2/src/main/java/com/baeldung/mockito/java8/JobPosition.java @@ -0,0 +1,20 @@ +package com.baeldung.mockito.java8; + +public class JobPosition { + private String title; + + public JobPosition() {} + + public JobPosition(String title) { + super(); + this.title = title; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/mockito2/src/main/java/com/baeldung/mockito/java8/JobService.java b/mockito2/src/main/java/com/baeldung/mockito/java8/JobService.java new file mode 100644 index 0000000000..85a59b18a4 --- /dev/null +++ b/mockito2/src/main/java/com/baeldung/mockito/java8/JobService.java @@ -0,0 +1,20 @@ +package com.baeldung.mockito.java8; + +import java.util.Optional; +import java.util.stream.Stream; + +public interface JobService { + Optional findCurrentJobPosition(Person person); + + default boolean assignJobPosition(Person person, JobPosition jobPosition) { + if (!findCurrentJobPosition(person).isPresent()) { + person.setCurrentJobPosition(jobPosition); + + return true; + } else { + return false; + } + } + + Stream listJobs(Person person); +} diff --git a/mockito2/src/main/java/com/baeldung/mockito/java8/Person.java b/mockito2/src/main/java/com/baeldung/mockito/java8/Person.java new file mode 100644 index 0000000000..4f7af49f9d --- /dev/null +++ b/mockito2/src/main/java/com/baeldung/mockito/java8/Person.java @@ -0,0 +1,28 @@ +package com.baeldung.mockito.java8; + +public class Person { + private String name; + private JobPosition currentJobPosition; + + public Person() {} + + public Person(String name) { + this.name = name; + } + + public JobPosition getCurrentJobPosition() { + return currentJobPosition; + } + + public void setCurrentJobPosition(JobPosition currentJobPosition) { + this.currentJobPosition = currentJobPosition; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/mockito2/src/main/java/com/baeldung/mockito/java8/UnemploymentService.java b/mockito2/src/main/java/com/baeldung/mockito/java8/UnemploymentService.java new file mode 100644 index 0000000000..5859ab31b0 --- /dev/null +++ b/mockito2/src/main/java/com/baeldung/mockito/java8/UnemploymentService.java @@ -0,0 +1,11 @@ +package com.baeldung.mockito.java8; + +import java.util.Optional; + +public interface UnemploymentService { + + boolean personIsEntitledToUnemploymentSupport(Person person); + + Optional searchJob(Person person, String searchString); + +} diff --git a/mockito2/src/main/java/com/baeldung/mockito/java8/UnemploymentServiceImpl.java b/mockito2/src/main/java/com/baeldung/mockito/java8/UnemploymentServiceImpl.java new file mode 100644 index 0000000000..6f189b46ea --- /dev/null +++ b/mockito2/src/main/java/com/baeldung/mockito/java8/UnemploymentServiceImpl.java @@ -0,0 +1,26 @@ +package com.baeldung.mockito.java8; + +import java.util.Optional; +import java.util.stream.Stream; + +public class UnemploymentServiceImpl implements UnemploymentService { + private final JobService jobService; + + public UnemploymentServiceImpl(JobService jobService) { + this.jobService = jobService; + } + + @Override + public boolean personIsEntitledToUnemploymentSupport(Person person) { + Optional optional = jobService.findCurrentJobPosition(person); + + return !optional.isPresent(); + } + + @Override + public Optional searchJob(Person person, String searchString) { + Stream stream = jobService.listJobs(person); + + return stream.filter((j) -> j.getTitle().contains(searchString)).findFirst(); + } +} diff --git a/mockito2/src/test/java/com/baeldung/mockito/java8/ArgumentMatcherWithLambdaUnitTest.java b/mockito2/src/test/java/com/baeldung/mockito/java8/ArgumentMatcherWithLambdaUnitTest.java new file mode 100644 index 0000000000..2efac513b7 --- /dev/null +++ b/mockito2/src/test/java/com/baeldung/mockito/java8/ArgumentMatcherWithLambdaUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.mockito.java8; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + + +public class ArgumentMatcherWithLambdaUnitTest { + + @InjectMocks + private UnemploymentServiceImpl unemploymentService; + + @Mock + private JobService jobService; + + @Test + public void whenPersonWithJob_thenIsNotEntitled() { + Person peter = new Person("Peter"); + Person linda = new Person("Linda"); + + JobPosition teacher = new JobPosition("Teacher"); + + when(jobService.findCurrentJobPosition( + ArgumentMatchers.argThat((p) -> p.getName().equals("Peter"))) + ).thenReturn(Optional.of(teacher)); + + assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(linda)); + assertFalse(unemploymentService.personIsEntitledToUnemploymentSupport(peter)); + } + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + } +} diff --git a/mockito2/src/test/java/com/baeldung/mockito/java8/ArgumentMatcherWithoutLambdaUnitTest.java b/mockito2/src/test/java/com/baeldung/mockito/java8/ArgumentMatcherWithoutLambdaUnitTest.java new file mode 100644 index 0000000000..786062ee57 --- /dev/null +++ b/mockito2/src/test/java/com/baeldung/mockito/java8/ArgumentMatcherWithoutLambdaUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.mockito.java8; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; + +import java.util.Optional; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + + +public class ArgumentMatcherWithoutLambdaUnitTest { + + @InjectMocks + private UnemploymentServiceImpl unemploymentService; + + @Mock + private JobService jobService; + + @Test + public void whenPersonWithJob_thenIsNotEntitled() { + Person peter = new Person("Peter"); + Person linda = new Person("Linda"); + + JobPosition teacher = new JobPosition("Teacher"); + + when(jobService.findCurrentJobPosition( + ArgumentMatchers.argThat(new PeterArgumentMatcher())) + ).thenReturn(Optional.of(teacher)); + + assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(linda)); + assertFalse(unemploymentService.personIsEntitledToUnemploymentSupport(peter)); + } + + private class PeterArgumentMatcher implements ArgumentMatcher { + + @Override + public boolean matches(Person p) { + return p + .getName() + .equals("Peter"); + } + } + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + } +} diff --git a/mockito2/src/test/java/com/baeldung/mockito/java8/CustomAnswerWithLambdaUnitTest.java b/mockito2/src/test/java/com/baeldung/mockito/java8/CustomAnswerWithLambdaUnitTest.java new file mode 100644 index 0000000000..06e9bca6d3 --- /dev/null +++ b/mockito2/src/test/java/com/baeldung/mockito/java8/CustomAnswerWithLambdaUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.mockito.java8; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +public class CustomAnswerWithLambdaUnitTest { + + @InjectMocks + private UnemploymentServiceImpl unemploymentService; + + @Mock + private JobService jobService; + + @Test + public void whenPersonWithJobHistory_thenSearchReturnsValue() { + Person peter = new Person("Peter"); + + assertEquals("Teacher", unemploymentService.searchJob(peter, "").get().getTitle()); + } + + @Test + public void whenPersonWithNoJobHistory_thenSearchReturnsEmpty() { + Person linda = new Person("Linda"); + + assertFalse(unemploymentService.searchJob(linda, "").isPresent()); + } + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + + when(jobService.listJobs(any(Person.class))).then((i) -> + Stream.of(new JobPosition("Teacher")) + .filter(p -> ((Person) i.getArgument(0)).getName().equals("Peter"))); + } +} diff --git a/mockito2/src/test/java/com/baeldung/mockito/java8/CustomAnswerWithoutLambdaUnitTest.java b/mockito2/src/test/java/com/baeldung/mockito/java8/CustomAnswerWithoutLambdaUnitTest.java new file mode 100644 index 0000000000..9d1aa3a3c0 --- /dev/null +++ b/mockito2/src/test/java/com/baeldung/mockito/java8/CustomAnswerWithoutLambdaUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.mockito.java8; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + + +public class CustomAnswerWithoutLambdaUnitTest { + + @InjectMocks + private UnemploymentServiceImpl unemploymentService; + + @Mock + private JobService jobService; + + @Test + public void whenPersonWithJobHistory_thenSearchReturnsValue() { + Person peter = new Person("Peter"); + + assertEquals("Teacher", unemploymentService.searchJob(peter, "").get().getTitle()); + } + + @Test + public void whenPersonWithNoJobHistory_thenSearchReturnsEmpty() { + Person linda = new Person("Linda"); + + assertFalse(unemploymentService.searchJob(linda, "").isPresent()); + } + + private class PersonAnswer implements Answer> { + + @Override + public Stream answer(InvocationOnMock invocation) throws Throwable { + Person person = invocation.getArgument(0); + + return Stream.of(new JobPosition("Teacher")) + .filter(p -> person.getName().equals("Peter")); + } + } + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + + when(jobService.listJobs(any(Person.class))).then(new PersonAnswer()); + } +} diff --git a/mockito2/src/test/java/com/baeldung/mockito/java8/JobServiceUnitTest.java b/mockito2/src/test/java/com/baeldung/mockito/java8/JobServiceUnitTest.java new file mode 100644 index 0000000000..9ea5c1db47 --- /dev/null +++ b/mockito2/src/test/java/com/baeldung/mockito/java8/JobServiceUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.mockito.java8; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +public class JobServiceUnitTest { + @Mock + private JobService jobService; + + @Test + public void givenDefaultMethod_whenCallRealMethod_thenNoExceptionIsRaised() { + Person person = new Person(); + + when(jobService.findCurrentJobPosition(person)).thenReturn(Optional.of(new JobPosition())); + doCallRealMethod().when(jobService).assignJobPosition(Mockito.any(Person.class), Mockito.any(JobPosition.class)); + + assertFalse(jobService.assignJobPosition(person, new JobPosition())); + } + + @Test + public void givenReturnIsOfTypeOptional_whenDefaultValueIsReturned_thenValueIsEmpty() { + Person person = new Person(); + + when(jobService.findCurrentJobPosition(person)).thenReturn(Optional.empty()); + doCallRealMethod().when(jobService).assignJobPosition(Mockito.any(Person.class), Mockito.any(JobPosition.class)); + + assertTrue(jobService.assignJobPosition(person, new JobPosition())); + } + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + } +} diff --git a/mockito2/src/test/java/com/baeldung/mockito/java8/UnemploymentServiceImplUnitTest.java b/mockito2/src/test/java/com/baeldung/mockito/java8/UnemploymentServiceImplUnitTest.java new file mode 100644 index 0000000000..b3b71e5bf9 --- /dev/null +++ b/mockito2/src/test/java/com/baeldung/mockito/java8/UnemploymentServiceImplUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.mockito.java8; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class UnemploymentServiceImplUnitTest { + @Mock + private JobService jobService; + + @InjectMocks + private UnemploymentServiceImpl unemploymentService; + + @Test + public void givenReturnIsOfTypeOptional_whenMocked_thenValueIsEmpty() { + Person person = new Person(); + + when(jobService.findCurrentJobPosition(any(Person.class))).thenReturn(Optional.empty()); + + assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(person)); + } + + @Test + public void givenReturnIsOfTypeOptional_whenDefaultValueIsReturned_thenValueIsEmpty() { + Person person = new Person(); + + // This will fail when Mockito 1 is used + assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(person)); + } + + @Test + public void givenReturnIsOfTypeStream_whenMocked_thenValueIsEmpty() { + Person person = new Person(); + + when(jobService.listJobs(any(Person.class))).thenReturn(Stream.empty()); + + assertFalse(unemploymentService.searchJob(person, "").isPresent()); + } + + @Test + public void givenReturnIsOfTypeStream_whenDefaultValueIsReturned_thenValueIsEmpty() { + Person person = new Person(); + + // This will fail when Mockito 1 is used + assertFalse(unemploymentService.searchJob(person, "").isPresent()); + } + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + } +} diff --git a/pdf/README.md b/pdf/README.md index 7160df4081..5454d2b2de 100644 --- a/pdf/README.md +++ b/pdf/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [PDF Conversions in Java](http://www.baeldung.com/pdf-conversions-java) +- [Creating PDF Files in Java](http://www.baeldung.com/java-pdf-creation) diff --git a/pom.xml b/pom.xml index 82df776044..9c24200a0b 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,6 @@ parent-modules pom - UTF-8 refs/heads/master @@ -47,10 +46,12 @@ guava guava18 guava19 + guice-intro disruptor handling-spring-static-resources hazelcast + httpclient hystrix @@ -62,9 +63,11 @@ javaslang javax-servlets javaxval + jasypt jaxb jee7 jjwt + jooq jpa-storedprocedure jsf json-path @@ -74,6 +77,7 @@ kotlin + libraries log-mdc log4j log4j2 @@ -83,6 +87,7 @@ metrics mesos-marathon mockito + mockito2 mocks orika @@ -93,6 +98,7 @@ querydsl + reactor-core redis rest-assured rest-testing @@ -194,16 +200,20 @@ struts2 apache-velocity + apache-solrj + + rabbitmq + - + diff --git a/rabbitmq/pom.xml b/rabbitmq/pom.xml new file mode 100644 index 0000000000..03f192e4e1 --- /dev/null +++ b/rabbitmq/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + com.baeldung + rabbitmq + 0.1-SNAPSHOT + + rabbitmq + http://maven.apache.org + + + + com.rabbitmq + amqp-client + 3.6.6 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + + + + UTF-8 + + 3.6.0 + + + \ No newline at end of file diff --git a/rabbitmq/src/main/java/com/baeldung/consumer/Receiver.java b/rabbitmq/src/main/java/com/baeldung/consumer/Receiver.java new file mode 100644 index 0000000000..d0612406e9 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/consumer/Receiver.java @@ -0,0 +1,31 @@ +package com.baeldung.consumer; + +import com.rabbitmq.client.*; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +public class Receiver { + + private static final String QUEUE_NAME = "products_queue"; + + public static void main (String[] args) throws IOException, TimeoutException { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost("localhost"); + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + channel.queueDeclare(QUEUE_NAME, false, false, false, null); + + Consumer consumer = new DefaultConsumer(channel) { + @Override + public void handleDelivery(String consumerTag, + Envelope envelope, AMQP.BasicProperties properties, + byte[] body) throws IOException { + String message = new String(body, "UTF-8"); + System.out.println(" [x] Received '" + message + "'"); + } + }; + channel.basicConsume(QUEUE_NAME, true, consumer); + } +} diff --git a/rabbitmq/src/main/java/com/baeldung/producer/Publisher.java b/rabbitmq/src/main/java/com/baeldung/producer/Publisher.java new file mode 100644 index 0000000000..f9130c5d86 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/producer/Publisher.java @@ -0,0 +1,27 @@ +package com.baeldung.producer; + +import com.rabbitmq.client.*; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +public class Publisher { + + private final static String QUEUE_NAME = "products_queue"; + + public static void main(String[]args) throws IOException, TimeoutException { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost("localhost"); + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + String message = "product details"; + channel.queueDeclare(QUEUE_NAME, false, false, false, null); + + channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); + System.out.println(" [x] Sent '" + message + "'"); + + channel.close(); + connection.close(); + } +} diff --git a/reactor-core/pom.xml b/reactor-core/pom.xml new file mode 100644 index 0000000000..3aeb4af3d5 --- /dev/null +++ b/reactor-core/pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + + org.baeldung + reactor-core + 0.0.1-SNAPSHOT + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + + io.projectreactor + reactor-core + ${reactor-core.version} + + + + junit + junit + ${junit.version} + test + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + + 3.0.5.RELEASE + 4.12 + 3.6.1 + 1.1.3 + + + diff --git a/reactor-core/src/test/java/com/baeldung/reactor/ReactorTest.java b/reactor-core/src/test/java/com/baeldung/reactor/ReactorTest.java new file mode 100644 index 0000000000..0e534e7d61 --- /dev/null +++ b/reactor-core/src/test/java/com/baeldung/reactor/ReactorTest.java @@ -0,0 +1,122 @@ +package com.baeldung.reactor; + +import org.junit.Test; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import reactor.core.publisher.ConnectableFlux; +import reactor.core.publisher.Flux; +import reactor.core.scheduler.Schedulers; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ReactorTest { + + @Test + public void givenFlux_whenSubscribing_thenStream() throws InterruptedException { + + List elements = new ArrayList<>(); + + Flux.just(1, 2, 3, 4) + .log() + .map(i -> { + System.out.println(i + ":" + Thread.currentThread()); + return i * 2; + }) + .subscribe(elements::add); + + assertThat(elements).containsExactly(2, 4, 6, 8); + } + + @Test + public void givenFlux_whenZipping_thenCombine() { + List elements = new ArrayList<>(); + + Flux.just(1, 2, 3, 4) + .log() + .map(i -> i * 2) + .zipWith(Flux.range(0, Integer.MAX_VALUE).log(), (two, one) -> String.format("First Flux: %d, Second Flux: %d", one, two)) + .subscribe(elements::add); + + assertThat(elements).containsExactly( + "First Flux: 0, Second Flux: 2", + "First Flux: 1, Second Flux: 4", + "First Flux: 2, Second Flux: 6", + "First Flux: 3, Second Flux: 8"); + } + + @Test + public void givenFlux_whenApplyingBackPressure_thenPushElementsInBatches() throws InterruptedException { + + List elements = new ArrayList<>(); + + Flux.just(1, 2, 3, 4) + .log() + .map(i -> i * 2) + .onBackpressureBuffer() + .subscribe(new Subscriber() { + private Subscription s; + int onNextAmount; + + @Override + public void onSubscribe(final Subscription s) { + this.s = s; + s.request(2); + } + + @Override + public void onNext(final Integer integer) { + elements.add(integer); + onNextAmount++; + if (onNextAmount % 2 == 0) { + s.request(2); + } + } + + @Override + public void onError(final Throwable t) { + } + + @Override + public void onComplete() { + int ham = 2; + } + }); + + assertThat(elements).containsExactly(2, 4, 6, 8); + } + + @Test + public void givenFlux_whenInParallel_thenSubscribeInDifferentThreads() throws InterruptedException { + List threadNames = new ArrayList<>(); + + Flux.just(1, 2, 3, 4) + .log() + .map(i -> Thread.currentThread().getName()) + .subscribeOn(Schedulers.parallel()) + .subscribe(threadNames::add); + + Thread.sleep(1000); + + assertThat(threadNames).containsExactly("parallel-1", "parallel-1", "parallel-1", "parallel-1"); + } + + @Test + public void givenConnectableFlux_whenConnected_thenShouldStream() { + + List elements = new ArrayList<>(); + + final ConnectableFlux publish = Flux.just(1, 2, 3, 4).publish(); + + publish.subscribe(elements::add); + + assertThat(elements).isEmpty(); + + publish.connect(); + + assertThat(elements).containsExactly(1, 2, 3, 4); + } + +} diff --git a/rxjava/README.md b/rxjava/README.md new file mode 100644 index 0000000000..7670dd4ed3 --- /dev/null +++ b/rxjava/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Dealing with Backpressure with RxJava](http://www.baeldung.com/rxjava-backpressure) +- [How to Test RxJava?](http://www.baeldung.com/rxjava-testing) diff --git a/solr-fulltext-search/pom.xml b/solr-fulltext-search/pom.xml index 4afcb5838a..bed6afd48f 100644 --- a/solr-fulltext-search/pom.xml +++ b/solr-fulltext-search/pom.xml @@ -18,7 +18,7 @@ org.apache.solr solr-solrj - 6.1.0 + 6.4.1 log4j diff --git a/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/model/Item.java b/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/model/Item.java new file mode 100644 index 0000000000..d7a0524ca9 --- /dev/null +++ b/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/model/Item.java @@ -0,0 +1,51 @@ +package com.baeldung.solr.fulltext.search.model; + +import org.apache.solr.client.solrj.beans.Field; + +public class Item { + + @Field + private String id; + + @Field + private String description; + + @Field + private String category; + + @Field + private float price; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } + +} diff --git a/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/service/ItemSearchService.java b/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/service/ItemSearchService.java new file mode 100644 index 0000000000..fa906fc975 --- /dev/null +++ b/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/service/ItemSearchService.java @@ -0,0 +1,15 @@ +package com.baeldung.solr.fulltext.search.service; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrServerException; + +import com.baeldung.solr.fulltext.search.model.Item; + +public interface ItemSearchService { + + public void index(String id, String description, String category, float price) throws SolrServerException, IOException; + + public void indexBean(Item item) throws IOException, SolrServerException; + +} diff --git a/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/service/ItemSearchServiceImpl.java b/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/service/ItemSearchServiceImpl.java new file mode 100644 index 0000000000..573cc58bc0 --- /dev/null +++ b/solr-fulltext-search/src/main/java/com/baeldung/solr/fulltext/search/service/ItemSearchServiceImpl.java @@ -0,0 +1,34 @@ +package com.baeldung.solr.fulltext.search.service; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.common.SolrInputDocument; + +import com.baeldung.solr.fulltext.search.model.Item; + +public class ItemSearchServiceImpl implements ItemSearchService { + + private final SolrClient solrClient; + + public ItemSearchServiceImpl(SolrClient solrClient) { + this.solrClient = solrClient; + } + + public void index(String id, String description, String category, float price) throws SolrServerException, IOException { + SolrInputDocument doc = new SolrInputDocument(); + doc.addField("id", id); + doc.addField("description", description); + doc.addField("category", category); + doc.addField("price", price); + solrClient.add(doc); + solrClient.commit(); + } + + public void indexBean(Item item) throws IOException, SolrServerException { + solrClient.addBean(item); + solrClient.commit(); + } + +} diff --git a/solr-fulltext-search/src/test/java/com/baeldung/solr/fulltext/search/service/ItemSearchServiceIntegrationTest.java b/solr-fulltext-search/src/test/java/com/baeldung/solr/fulltext/search/service/ItemSearchServiceIntegrationTest.java new file mode 100644 index 0000000000..94661ffc2e --- /dev/null +++ b/solr-fulltext-search/src/test/java/com/baeldung/solr/fulltext/search/service/ItemSearchServiceIntegrationTest.java @@ -0,0 +1,374 @@ +package com.baeldung.solr.fulltext.search.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.List; +import java.util.Map; + +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.response.FacetField.Count; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.client.solrj.response.RangeFacet; +import org.apache.solr.client.solrj.response.SpellCheckResponse; +import org.apache.solr.client.solrj.response.SpellCheckResponse.Suggestion; +import org.apache.solr.client.solrj.response.SuggesterResponse; +import org.apache.solr.common.SolrDocument; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.solr.fulltext.search.model.Item; + +public class ItemSearchServiceIntegrationTest { + + private static SolrClient solrClient; + private static ItemSearchService itemSearchService; + private static final String solrUrl = "http://localhost:8987/solr/item"; + + @BeforeClass + public static void initBeans() throws Exception { + solrClient = new HttpSolrClient.Builder(solrUrl).build(); + itemSearchService = new ItemSearchServiceImpl(solrClient); + + solrClient.commit(); + } + + @Before + public void clearSolrData() throws Exception { + solrClient.deleteByQuery("*:*"); + } + + @Test + public void whenIndexing_thenAvailableOnRetrieval() throws Exception { + itemSearchService.index("hm0001", "Washing Machine", "Home Appliances", 450f); + final SolrDocument indexedDoc = solrClient.getById("hm0001"); + assertEquals("hm0001", indexedDoc.get("id")); + } + + @Test + public void whenIndexingBean_thenAvailableOnRetrieval() throws Exception { + Item item = new Item(); + item.setId("hm0002"); + item.setCategory("Televisions"); + item.setDescription("LED TV 32"); + item.setPrice(500); + itemSearchService.indexBean(item); + } + + @Test + public void whenSearchingByBasicQuery_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("brand1"); + query.setStart(0); + query.setRows(10); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(3, items.size()); + + } + + @Test + public void whenSearchingWithWildCard_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("*rand?"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(3, items.size()); + } + + @Test + public void whenSearchingWithLogicalOperators_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("hm0003", "Brand2 LED TV 32", "Washing Appliances", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("brand1 AND (Washing OR Refrigerator)"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(2, items.size()); + } + + @Test + public void whenSearchingWithFields_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("0003", "Brand2 LED TV 32", "Brand1 Washing Home Appliances", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("description:Brand* AND category:*Washing*"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(1, items.size()); + } + + @Test + public void whenSearchingWithPhrase_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("washing MachIne"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(2, items.size()); + } + + @Test + public void whenSearchingWithRealPhrase_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("\"washing machine\""); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(1, items.size()); + } + + @Test + public void whenSearchingPhraseWithProximity_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f); + itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("\"Washing equipment\"~2"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(1, items.size()); + } + + @Test + public void whenSearchingWithPriceRange_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); + itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("price:[100 TO 300]"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(3, items.size()); + } + + @Test + public void whenSearchingWithPriceRangeInclusiveExclusive_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); + itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f); + + SolrQuery query = new SolrQuery(); + query.setQuery("price:{100 TO 300]"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(2, items.size()); + } + + @Test + public void whenSearchingWithFilterQuery_thenAllMatchingItemsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 250f); + + SolrQuery query = new SolrQuery(); + query.setQuery("price:[100 TO 300]"); + query.addFilterQuery("description:Brand1", "category:Home Appliances"); + + QueryResponse response = solrClient.query(query); + List items = response.getBeans(Item.class); + + assertEquals(2, items.size()); + } + + @Test + public void whenSearchingWithFacetFields_thenAllMatchingFacetsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f); + + SolrQuery query = new SolrQuery(); + query.setQuery("*:*"); + query.addFacetField("category"); + + QueryResponse response = solrClient.query(query); + List facetResults = response.getFacetField("category").getValues(); + + assertEquals(2, facetResults.size()); + + for (Count count : facetResults) { + if ("categorya".equalsIgnoreCase(count.getName())) { + assertEquals(2, count.getCount()); + } else if ("categoryb".equalsIgnoreCase(count.getName())) { + assertEquals(2, count.getCount()); + } else { + fail("unexpected category"); + } + } + } + + @Test + public void whenSearchingWithFacetQuery_thenAllMatchingFacetsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f); + + SolrQuery query = new SolrQuery(); + query.setQuery("*:*"); + + query.addFacetQuery("Washing OR Refrigerator"); + query.addFacetQuery("Brand2"); + + QueryResponse response = solrClient.query(query); + Map facetQueryMap = response.getFacetQuery(); + + assertEquals(2, facetQueryMap.size()); + + for (Map.Entry entry : facetQueryMap.entrySet()) { + String facetQuery = entry.getKey(); + + if ("Washing OR Refrigerator".equals(facetQuery)) { + assertEquals(Integer.valueOf(2), entry.getValue()); + } else if ("Brand2".equals(facetQuery)) { + assertEquals(Integer.valueOf(2), entry.getValue()); + } else { + fail("unexpected query"); + } + + } + } + + @Test + public void whenSearchingWithFacetRange_thenAllMatchingFacetsShouldAvialble() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 125f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 150f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f); + + SolrQuery query = new SolrQuery(); + query.setQuery("*:*"); + + query.addNumericRangeFacet("price", 100, 275, 25); + + QueryResponse response = solrClient.query(query); + List rangeFacets = response.getFacetRanges().get(0).getCounts(); + + assertEquals(7, rangeFacets.size()); + } + + @Test + public void whenSearchingWithHitHighlighting_thenKeywordsShouldBeHighlighted() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f); + + SolrQuery query = new SolrQuery(); + query.setQuery("Appliances"); + query.setHighlight(true); + query.addHighlightField("category"); + query.setHighlightSimplePre(""); + query.setHighlightSimplePost(""); + QueryResponse response = solrClient.query(query); + + Map>> hitHighlightedMap = response.getHighlighting(); + Map> highlightedFieldMap = hitHighlightedMap.get("hm0001"); + List highlightedList = highlightedFieldMap.get("category"); + String highLightedText = highlightedList.get(0); + + assertEquals("Home Appliances", highLightedText); + + } + + @Test + public void whenSearchingWithKeywordWithMistake_thenSpellingSuggestionsShouldBeReturned() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f); + + SolrQuery query = new SolrQuery(); + query.setQuery("hme"); + query.set("spellcheck", "on"); + QueryResponse response = solrClient.query(query); + + SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse(); + + assertEquals(false, spellCheckResponse.isCorrectlySpelled()); + + Suggestion suggestion = spellCheckResponse.getSuggestions().get(0); + + assertEquals("hme", suggestion.getToken()); + + List alternatives = suggestion.getAlternatives(); + String alternative = alternatives.get(0); + + assertEquals("home", alternative); + } + + @Test + public void whenSearchingWithIncompleteKeyword_thenKeywordSuggestionsShouldBeReturned() throws Exception { + itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f); + itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f); + itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f); + itemSearchService.index("hm0004", "Brand2 Dishwasher", "Home washing equipments", 250f); + + SolrQuery query = new SolrQuery(); + query.setRequestHandler("/suggest"); + query.set("suggest", "true"); + query.set("suggest.build", "true"); + query.set("suggest.dictionary", "mySuggester"); + query.set("suggest.q", "Hom"); + QueryResponse response = solrClient.query(query); + + SuggesterResponse suggesterResponse = response.getSuggesterResponse(); + Map> suggestedTerms = suggesterResponse.getSuggestedTerms(); + List suggestions = suggestedTerms.get("mySuggester"); + + assertEquals(2, suggestions.size()); + + for (String term : suggestions) { + if (!"Home Appliances".equals(term) && !"Home washing equipments".equals(term)) { + fail("Unexpected suggestions"); + } + } + + } + +} diff --git a/spring-5/.gitignore b/spring-5/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-5/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-5/README.md b/spring-5/README.md new file mode 100644 index 0000000000..0914388b49 --- /dev/null +++ b/spring-5/README.md @@ -0,0 +1,6 @@ +## Spring REST Example Project + +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: diff --git a/spring-5/pom.xml b/spring-5/pom.xml new file mode 100644 index 0000000000..ab05918ae4 --- /dev/null +++ b/spring-5/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + com.baeldung + spring-5 + 0.0.1-SNAPSHOT + jar + + spring-5 + + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.BUILD-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-web + + + + + org.apache.commons + commons-lang3 + + + + + + org.springframework.boot + spring-boot-devtools + runtime + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + 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 + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + UTF-8 + UTF-8 + 1.8 + + + diff --git a/spring-5/src/main/java/com/baeldung/Spring5Application.java b/spring-5/src/main/java/com/baeldung/Spring5Application.java new file mode 100644 index 0000000000..41b5c1eed1 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/Spring5Application.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Spring5Application { + + public static void main(String[] args) { + SpringApplication.run(Spring5Application.class, args); + } + +} diff --git a/spring-5/src/main/java/com/baeldung/persistence/DataSetupBean.java b/spring-5/src/main/java/com/baeldung/persistence/DataSetupBean.java new file mode 100644 index 0000000000..7936a2b7af --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/persistence/DataSetupBean.java @@ -0,0 +1,26 @@ +package com.baeldung.persistence; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import java.util.stream.IntStream; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.web.Foo; + +@Component +public class DataSetupBean implements InitializingBean { + + @Autowired + private FooRepository repo; + + // + + @Override + public void afterPropertiesSet() throws Exception { + IntStream.range(1, 20).forEach(i -> repo.save(new Foo(randomAlphabetic(8)))); + } + +} diff --git a/spring-5/src/main/java/com/baeldung/persistence/FooRepository.java b/spring-5/src/main/java/com/baeldung/persistence/FooRepository.java new file mode 100644 index 0000000000..1f1e071158 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/persistence/FooRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import com.baeldung.web.Foo; + +public interface FooRepository extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/spring-5/src/main/java/com/baeldung/web/Foo.java b/spring-5/src/main/java/com/baeldung/web/Foo.java new file mode 100644 index 0000000000..c4868a9958 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/web/Foo.java @@ -0,0 +1,84 @@ +package com.baeldung.web; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Foo { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + public Foo(final long id, final String name) { + super(); + + this.id = id; + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + return "Foo [name=" + name + "]"; + } + +} \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/web/FooController.java b/spring-5/src/main/java/com/baeldung/web/FooController.java new file mode 100644 index 0000000000..de6928033e --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/web/FooController.java @@ -0,0 +1,62 @@ +package com.baeldung.web; + +import java.util.List; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.persistence.FooRepository; + +@RestController("/foos") +public class FooController { + + @Autowired + private FooRepository repo; + + // API - read + + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + @ResponseBody + @Validated + public Foo findById(@PathVariable @Min(0) final long id) { + return repo.findOne(id); + } + + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public List findAll() { + return repo.findAll(); + } + + @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET) + @ResponseBody + @Validated + public List findPaginated(@RequestParam("page") @Min(0) final int page, @Max(100) @RequestParam("size") final int size) { + final Page resultPage = repo.findAll(new PageRequest(page, size)); + return resultPage.getContent(); + } + + // API - write + + @RequestMapping(method = RequestMethod.PUT, value = "/foos/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo update(@PathVariable("id") final String id, @RequestBody final Foo foo) { + return foo; + } + +} diff --git a/spring-5/src/main/resources/application.properties b/spring-5/src/main/resources/application.properties new file mode 100644 index 0000000000..886ea1978b --- /dev/null +++ b/spring-5/src/main/resources/application.properties @@ -0,0 +1,6 @@ +server.port=8081 + +security.user.name=user +security.user.password=pass + +logging.level.root=INFO \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/IntegrationTestExample1.java b/spring-5/src/test/java/com/baeldung/IntegrationTestExample1.java new file mode 100644 index 0000000000..0a27be4a95 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/IntegrationTestExample1.java @@ -0,0 +1,29 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class IntegrationTestExample1 { + + @Test + public void test1a() { + block(3000); + } + + @Test + public void test1b() { + block(3000); + } + + public static void block(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Thread interrupted"); + } + } +} diff --git a/spring-5/src/test/java/com/baeldung/IntegrationTestExample2.java b/spring-5/src/test/java/com/baeldung/IntegrationTestExample2.java new file mode 100644 index 0000000000..0bb2d47ef5 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/IntegrationTestExample2.java @@ -0,0 +1,29 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class IntegrationTestExample2 { + + @Test + public void test1a() { + block(3000); + } + + @Test + public void test1b() { + block(3000); + } + + public static void block(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Thread Interrupted"); + } + } +} diff --git a/spring-5/src/test/java/com/baeldung/ParallelTestExample.java b/spring-5/src/test/java/com/baeldung/ParallelTestExample.java new file mode 100644 index 0000000000..e73b8d4649 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/ParallelTestExample.java @@ -0,0 +1,24 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.experimental.ParallelComputer; +import org.junit.runner.Computer; +import org.junit.runner.JUnitCore; + +public class ParallelTestExample { + + @Test + public void runTests() { + final Class[] classes = { IntegrationTestExample1.class, IntegrationTestExample2.class }; + + JUnitCore.runClasses(new Computer(), classes); + } + + @Test + public void runTestsInParallel() { + final Class[] classes = { IntegrationTestExample1.class, IntegrationTestExample2.class }; + + JUnitCore.runClasses(new ParallelComputer(true, true), classes); + } + +} \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/Spring5ApplicationTests.java b/spring-5/src/test/java/com/baeldung/Spring5ApplicationTests.java new file mode 100644 index 0000000000..537ec56a89 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/Spring5ApplicationTests.java @@ -0,0 +1,16 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class Spring5ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-all/README.md b/spring-all/README.md index 90ae69300a..a8ea7c58c7 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -16,3 +16,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Quick Guide to Spring Controllers](http://www.baeldung.com/spring-controllers) - [Quick Guide to Spring Bean Scopes](http://www.baeldung.com/spring-bean-scopes) - [Introduction To Ehcache](http://www.baeldung.com/ehcache) +- [A Guide to the Spring Task Scheduler](http://www.baeldung.com/spring-task-scheduler) +- [Guide to Spring Retry](http://www.baeldung.com/spring-retry) diff --git a/spring-all/src/main/java/org/baeldung/bean/config/ConstructorBasedShipConfig.java b/spring-all/src/main/java/org/baeldung/bean/config/ConstructorBasedShipConfig.java new file mode 100644 index 0000000000..f0e6e8868e --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/bean/config/ConstructorBasedShipConfig.java @@ -0,0 +1,20 @@ +package org.baeldung.bean.config; + +import org.baeldung.bean.injection.Helm; +import org.baeldung.bean.injection.Ship; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ConstructorBasedShipConfig { + + @Bean + public Ship ship() { + return new Ship(helm()); + } + + @Bean + public Helm helm() { + return new Helm(); + } +} diff --git a/spring-all/src/main/java/org/baeldung/bean/config/SetterBasedShipConfig.java b/spring-all/src/main/java/org/baeldung/bean/config/SetterBasedShipConfig.java new file mode 100644 index 0000000000..7cd6de1c74 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/bean/config/SetterBasedShipConfig.java @@ -0,0 +1,18 @@ +package org.baeldung.bean.config; + +import org.baeldung.bean.injection.Helm; +import org.baeldung.bean.injection.Ship; +import org.springframework.context.annotation.Bean; + +public class SetterBasedShipConfig { + + @Bean + public Ship ship() { + return new Ship(); + } + + @Bean + public Helm helm() { + return new Helm(); + } +} diff --git a/spring-all/src/main/java/org/baeldung/bean/injection/Helm.java b/spring-all/src/main/java/org/baeldung/bean/injection/Helm.java new file mode 100644 index 0000000000..6d6ea85482 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/bean/injection/Helm.java @@ -0,0 +1,14 @@ +package org.baeldung.bean.injection; + +public class Helm { + + private String brandOfHelm = "HelmBrand"; + + public String getBrandOfHelm() { + return brandOfHelm; + } + + public void setBrandOfHelm(String brandOfHelm) { + this.brandOfHelm = brandOfHelm; + } +} diff --git a/spring-all/src/main/java/org/baeldung/bean/injection/Ship.java b/spring-all/src/main/java/org/baeldung/bean/injection/Ship.java new file mode 100644 index 0000000000..69d9fa1276 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/bean/injection/Ship.java @@ -0,0 +1,26 @@ +package org.baeldung.bean.injection; + +import org.springframework.beans.factory.annotation.Autowired; + +public class Ship { + + @Autowired + private Helm helm; + + public Ship() { + helm = new Helm(); + } + + public Ship(Helm helm) { + this.helm = helm; + } + + @Autowired + public void setHelm(Helm helm) { + this.helm = helm; + } + + public Helm getHelm() { + return this.helm; + } +} diff --git a/spring-all/src/main/resources/basicConfigForPropertiesTwo.xml b/spring-all/src/main/resources/basicConfigForPropertiesTwo.xml index bd6588104f..1d470c4340 100644 --- a/spring-all/src/main/resources/basicConfigForPropertiesTwo.xml +++ b/spring-all/src/main/resources/basicConfigForPropertiesTwo.xml @@ -1,12 +1,13 @@ - + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> - + \ No newline at end of file diff --git a/spring-all/src/main/resources/beanInjection-constructor.xml b/spring-all/src/main/resources/beanInjection-constructor.xml new file mode 100644 index 0000000000..a0713fd9f8 --- /dev/null +++ b/spring-all/src/main/resources/beanInjection-constructor.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-all/src/main/resources/beanInjection-setter.xml b/spring-all/src/main/resources/beanInjection-setter.xml new file mode 100644 index 0000000000..b07826c31e --- /dev/null +++ b/spring-all/src/main/resources/beanInjection-setter.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-all/src/test/java/org/baeldung/bean/injection/ConstructorBasedBeanInjectionWithJavaConfigTest.java b/spring-all/src/test/java/org/baeldung/bean/injection/ConstructorBasedBeanInjectionWithJavaConfigTest.java new file mode 100644 index 0000000000..68f8fc13d9 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/bean/injection/ConstructorBasedBeanInjectionWithJavaConfigTest.java @@ -0,0 +1,23 @@ +package org.baeldung.bean.injection; + +import org.baeldung.bean.config.ConstructorBasedShipConfig; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class ConstructorBasedBeanInjectionWithJavaConfigTest { + private static final String HELM_NAME = "HelmBrand"; + + @Test + public void givenJavaConfigFile_whenUsingConstructorBasedBeanInjection_thenCorrectHelmName() { + + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(ConstructorBasedShipConfig.class); + ctx.refresh(); + + Ship ship = ctx.getBean(Ship.class); + + Assert.assertEquals(HELM_NAME, ship.getHelm() + .getBrandOfHelm()); + } +} diff --git a/spring-all/src/test/java/org/baeldung/bean/injection/ConstructorBasedBeanInjectionWithXMLConfigTest.java b/spring-all/src/test/java/org/baeldung/bean/injection/ConstructorBasedBeanInjectionWithXMLConfigTest.java new file mode 100644 index 0000000000..e69de124b2 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/bean/injection/ConstructorBasedBeanInjectionWithXMLConfigTest.java @@ -0,0 +1,20 @@ +package org.baeldung.bean.injection; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class ConstructorBasedBeanInjectionWithXMLConfigTest { + + private static final String HELM_NAME = "HelmBrand"; + + @Test + public void givenXMLConfigFile_whenUsingConstructorBasedBeanInjection_thenCorrectHelmName() { + final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beanInjection-constructor.xml"); + + final Ship shipConstructorBean = (Ship) applicationContext.getBean("ship"); + Assert.assertEquals(HELM_NAME, shipConstructorBean.getHelm() + .getBrandOfHelm()); + } +} diff --git a/spring-all/src/test/java/org/baeldung/bean/injection/SetterBasedBeanInjectionWithJavaConfigTest.java b/spring-all/src/test/java/org/baeldung/bean/injection/SetterBasedBeanInjectionWithJavaConfigTest.java new file mode 100644 index 0000000000..8705995acd --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/bean/injection/SetterBasedBeanInjectionWithJavaConfigTest.java @@ -0,0 +1,24 @@ +package org.baeldung.bean.injection; + +import org.baeldung.bean.config.SetterBasedShipConfig; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class SetterBasedBeanInjectionWithJavaConfigTest { + + private static final String HELM_NAME = "HelmBrand"; + + @Test + public void givenJavaConfigFile_whenUsingSetterBasedBeanInjection_thenCorrectHelmName() { + + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(SetterBasedShipConfig.class); + ctx.refresh(); + + Ship ship = ctx.getBean(Ship.class); + + Assert.assertEquals(HELM_NAME, ship.getHelm() + .getBrandOfHelm()); + } +} diff --git a/spring-all/src/test/java/org/baeldung/bean/injection/SetterBasedBeanInjectionWithXMLConfigTest.java b/spring-all/src/test/java/org/baeldung/bean/injection/SetterBasedBeanInjectionWithXMLConfigTest.java new file mode 100644 index 0000000000..1958761d78 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/bean/injection/SetterBasedBeanInjectionWithXMLConfigTest.java @@ -0,0 +1,20 @@ +package org.baeldung.bean.injection; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class SetterBasedBeanInjectionWithXMLConfigTest { + + private static final String HELM_NAME = "HelmBrand"; + + @Test + public void givenXMLConfigFile_whenUsingSetterBasedBeanInjection_thenCorrectHelmName() { + final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beanInjection-setter.xml"); + + final Ship shipSetterBean = (Ship) applicationContext.getBean("ship"); + Assert.assertEquals(HELM_NAME, shipSetterBean.getHelm() + .getBrandOfHelm()); + } +} diff --git a/spring-amqp/README.md b/spring-amqp/README.md new file mode 100644 index 0000000000..b0d16c9305 --- /dev/null +++ b/spring-amqp/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Messaging With Spring AMQP](http://www.baeldung.com/spring-amqp) diff --git a/spring-boot-auditing/.gitignore b/spring-boot-auditing/.gitignore new file mode 100644 index 0000000000..31ce405488 --- /dev/null +++ b/spring-boot-auditing/.gitignore @@ -0,0 +1,6 @@ +/target/ +.settings/ +.classpath +.project +*.iml +.idea \ No newline at end of file diff --git a/spring-boot-auditing/pom.xml b/spring-boot-auditing/pom.xml new file mode 100644 index 0000000000..9307db39ee --- /dev/null +++ b/spring-boot-auditing/pom.xml @@ -0,0 +1,198 @@ + + 4.0.0 + com.baeldung + spring-boot-auditing + 0.0.1-SNAPSHOT + war + spring-boot-auditing + This is simple boot application for Spring boot auditing test + + + + org.springframework.boot + spring-boot-starter-parent + 1.5.1.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-security + + + + io.dropwizard.metrics + metrics-core + + + + com.h2database + h2 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter + + + com.jayway.jsonpath + json-path + test + + + org.springframework.boot + spring-boot-starter-mail + + + org.subethamail + subethasmtp + ${subethasmtp.version} + test + + + + org.webjars + bootstrap + ${bootstrap.version} + + + org.webjars + jquery + ${jquery.version} + + + + org.apache.tomcat + tomcat-servlet-api + ${tomee-servlet-api.version} + provided + + + + + + spring-boot + + + src/main/resources + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + + + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + + 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 + + + + + + + + + + + UTF-8 + 1.8 + 4.3.4.RELEASE + 2.2.1 + 3.1.1 + 3.3.7-1 + 3.1.7 + 8.5.11 + + + diff --git a/spring-boot-auditing/src/main/java/org/baeldung/Application.java b/spring-boot-auditing/src/main/java/org/baeldung/Application.java new file mode 100755 index 0000000000..bf7b7bd1a6 --- /dev/null +++ b/spring-boot-auditing/src/main/java/org/baeldung/Application.java @@ -0,0 +1,13 @@ +package org.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) throws Throwable { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-boot-auditing/src/main/java/org/baeldung/MvcConfig.java b/spring-boot-auditing/src/main/java/org/baeldung/MvcConfig.java new file mode 100755 index 0000000000..fecb8c5c0b --- /dev/null +++ b/spring-boot-auditing/src/main/java/org/baeldung/MvcConfig.java @@ -0,0 +1,18 @@ +package org.baeldung; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/home").setViewName("home"); + registry.addViewController("/").setViewName("home"); + registry.addViewController("/hello").setViewName("hello"); + registry.addViewController("/login").setViewName("login"); + } + +} diff --git a/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java b/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java new file mode 100755 index 0000000000..199edce0bc --- /dev/null +++ b/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java @@ -0,0 +1,34 @@ +package org.baeldung; + +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.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/", "/home").permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login") + .permitAll() + .and() + .logout() + .permitAll(); + } + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("user").password("password").roles("USER"); + } +} diff --git a/spring-boot-auditing/src/main/java/org/baeldung/auditing/ExposeAttemptedPathAuthorizationAuditListener.java b/spring-boot-auditing/src/main/java/org/baeldung/auditing/ExposeAttemptedPathAuthorizationAuditListener.java new file mode 100644 index 0000000000..bc36ac08b3 --- /dev/null +++ b/spring-boot-auditing/src/main/java/org/baeldung/auditing/ExposeAttemptedPathAuthorizationAuditListener.java @@ -0,0 +1,36 @@ +package org.baeldung.auditing; + +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.boot.actuate.security.AbstractAuthorizationAuditListener; +import org.springframework.security.access.event.AbstractAuthorizationEvent; +import org.springframework.security.access.event.AuthorizationFailureEvent; +import org.springframework.security.web.FilterInvocation; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class ExposeAttemptedPathAuthorizationAuditListener extends AbstractAuthorizationAuditListener { + + public static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE"; + + @Override + public void onApplicationEvent(AbstractAuthorizationEvent event) { + if (event instanceof AuthorizationFailureEvent) { + onAuthorizationFailureEvent((AuthorizationFailureEvent) event); + } + } + + private void onAuthorizationFailureEvent(AuthorizationFailureEvent event) { + Map data = new HashMap<>(); + data.put("type", event.getAccessDeniedException().getClass().getName()); + data.put("message", event.getAccessDeniedException().getMessage()); + data.put("requestUrl", ((FilterInvocation)event.getSource()).getRequestUrl() ); + if (event.getAuthentication().getDetails() != null) { + data.put("details", event.getAuthentication().getDetails()); + } + publish(new AuditEvent(event.getAuthentication().getName(), AUTHORIZATION_FAILURE, + data)); + } +} diff --git a/spring-boot-auditing/src/main/java/org/baeldung/auditing/LoginAttemptsLogger.java b/spring-boot-auditing/src/main/java/org/baeldung/auditing/LoginAttemptsLogger.java new file mode 100644 index 0000000000..5be8cebfd3 --- /dev/null +++ b/spring-boot-auditing/src/main/java/org/baeldung/auditing/LoginAttemptsLogger.java @@ -0,0 +1,25 @@ +package org.baeldung.auditing; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.boot.actuate.audit.listener.AuditApplicationEvent; +import org.springframework.context.event.EventListener; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.stereotype.Component; + +@Component +public class LoginAttemptsLogger { + private static final Logger LOGGER = LoggerFactory.getLogger(LoginAttemptsLogger.class); + + @EventListener + public void auditEventHappened(AuditApplicationEvent auditApplicationEvent) { + AuditEvent auditEvent = auditApplicationEvent.getAuditEvent(); + LOGGER.debug("Principal " + auditEvent.getPrincipal() + " - " + auditEvent.getType()); + + WebAuthenticationDetails details = (WebAuthenticationDetails) auditEvent.getData().get("details"); + LOGGER.debug(" Remote IP address: " + details.getRemoteAddress()); + LOGGER.debug(" Session Id: " + details.getSessionId()); + LOGGER.debug(" Request URL: " + auditEvent.getData().get("requestUrl")); + } +} diff --git a/spring-boot-auditing/src/main/resources/application.properties b/spring-boot-auditing/src/main/resources/application.properties new file mode 100644 index 0000000000..cf09473b60 --- /dev/null +++ b/spring-boot-auditing/src/main/resources/application.properties @@ -0,0 +1 @@ +logging.level.org.springframework=INFO \ No newline at end of file diff --git a/spring-boot-auditing/src/main/resources/logback.xml b/spring-boot-auditing/src/main/resources/logback.xml new file mode 100644 index 0000000000..78913ee76f --- /dev/null +++ b/spring-boot-auditing/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-auditing/src/main/resources/templates/hello.html b/spring-boot-auditing/src/main/resources/templates/hello.html new file mode 100755 index 0000000000..46feef7e2c --- /dev/null +++ b/spring-boot-auditing/src/main/resources/templates/hello.html @@ -0,0 +1,13 @@ + + + + Hello World! + + +

Hello [[${#httpServletRequest.remoteUser}]]!

+
+ +
+ + \ No newline at end of file diff --git a/spring-boot-auditing/src/main/resources/templates/home.html b/spring-boot-auditing/src/main/resources/templates/home.html new file mode 100755 index 0000000000..fe4e8b337e --- /dev/null +++ b/spring-boot-auditing/src/main/resources/templates/home.html @@ -0,0 +1,11 @@ + + + + Spring Security Example + + +

Welcome!

+ +

Click here to see a greeting.

+ + \ No newline at end of file diff --git a/spring-boot-auditing/src/main/resources/templates/login.html b/spring-boot-auditing/src/main/resources/templates/login.html new file mode 100755 index 0000000000..a1785313f5 --- /dev/null +++ b/spring-boot-auditing/src/main/resources/templates/login.html @@ -0,0 +1,20 @@ + + + + Spring Security Example + + +
+ Invalid username and password. +
+
+ You have been logged out. +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 05173ef318..9fe18aaacc 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -7,3 +7,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Guide to Spring in Eclipse STS](http://www.baeldung.com/eclipse-sts-spring) - [Introduction to WebJars](http://www.baeldung.com/maven-webjars) - [Create a Fat Jar App with Spring Boot](http://www.baeldung.com/deployable-fat-jar-spring-boot) +- [The @ServletComponentScan Annotation in Spring Boot](http://www.baeldung.com/spring-servletcomponentscan) +- [A Custom Data Binder in Spring MVC](http://www.baeldung.com/spring-mvc-custom-data-binder) +- [Intro to Building an Application with Spring Boot](http://www.baeldung.com/intro-to-spring-boot) +- [How to Register a Servlet in a Java Web Application](http://www.baeldung.com/register-servlet) diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index e77ab10aff..65b0f247f8 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -41,6 +41,24 @@ spring-boot-starter-security
+ + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.version} + + + + org.apache.tomcat.embed + tomcat-embed-jasper + ${tomcat.version} + + io.dropwizard.metrics metrics-core diff --git a/spring-boot/src/main/java/com/baeldung/servlets/ApplicationMain.java b/spring-boot/src/main/java/com/baeldung/servlets/ApplicationMain.java new file mode 100644 index 0000000000..a6ea3757fe --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/ApplicationMain.java @@ -0,0 +1,19 @@ +package com.baeldung.servlets; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; + +@SpringBootApplication +public class ApplicationMain extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(ApplicationMain.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(ApplicationMain.class); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/configuration/WebAppInitializer.java b/spring-boot/src/main/java/com/baeldung/servlets/configuration/WebAppInitializer.java new file mode 100644 index 0000000000..eadd40355a --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/configuration/WebAppInitializer.java @@ -0,0 +1,32 @@ +package com.baeldung.servlets.configuration; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.XmlWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +public class WebAppInitializer implements WebApplicationInitializer { + + public void onStartup(ServletContext container) throws ServletException { + + AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); + ctx.register(WebMvcConfigure.class); + ctx.setServletContext(container); + + ServletRegistration.Dynamic servletOne = container.addServlet("SpringProgrammaticDispatcherServlet", new DispatcherServlet(ctx)); + servletOne.setLoadOnStartup(1); + servletOne.addMapping("/"); + + XmlWebApplicationContext xctx = new XmlWebApplicationContext(); + xctx.setConfigLocation("/WEB-INF/context.xml"); + xctx.setServletContext(container); + + ServletRegistration.Dynamic servletTwo = container.addServlet("SpringProgrammaticXMLDispatcherServlet", new DispatcherServlet(xctx)); + servletTwo.setLoadOnStartup(1); + servletTwo.addMapping("/"); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/configuration/WebMvcConfigure.java b/spring-boot/src/main/java/com/baeldung/servlets/configuration/WebMvcConfigure.java new file mode 100644 index 0000000000..3d6a10c2ac --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/configuration/WebMvcConfigure.java @@ -0,0 +1,39 @@ +package com.baeldung.servlets.configuration; + +import org.springframework.boot.web.support.ErrorPageFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.resource.PathResourceResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +public class WebMvcConfigure extends WebMvcConfigurerAdapter { + + @Bean + public ViewResolver getViewResolver() { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setPrefix("/WEB-INF/"); + resolver.setSuffix(".jsp"); + return resolver; + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver()); + } + + @Bean + public ErrorPageFilter errorPageFilter() { + return new ErrorPageFilter(); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/props/Constants.java b/spring-boot/src/main/java/com/baeldung/servlets/props/Constants.java new file mode 100644 index 0000000000..6345d1f969 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/props/Constants.java @@ -0,0 +1,20 @@ +package com.baeldung.servlets.props; + +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Properties; + +public final class Constants { + + @Autowired + PropertySourcesLoader psl; + + public static final String breakLine = System.getProperty("line.separator"); + private static final PropertyLoader pl = new PropertyLoader(); + private static final Properties mainProps = pl.getProperties("custom.properties"); + public static final String DISPATCHER_SERVLET_NAME = mainProps.getProperty("dispatcher.servlet.name"); + public static final String DISPATCHER_SERVLET_MAPPING = mainProps.getProperty("dispatcher.servlet.mapping"); + private final String EXAMPLE_SERVLET_NAME = psl.getProperty("example.servlet.name"); + private final String EXAMPLE_SERVLET_MAPPING = psl.getProperty("example.servlet.mapping"); + +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/props/PropertyLoader.java b/spring-boot/src/main/java/com/baeldung/servlets/props/PropertyLoader.java new file mode 100644 index 0000000000..c29da45929 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/props/PropertyLoader.java @@ -0,0 +1,27 @@ +package com.baeldung.servlets.props; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class PropertyLoader { + private static final Logger log = LoggerFactory.getLogger(PropertyLoader.class); + + public Properties getProperties(String file) { + Properties prop = new Properties(); + InputStream input = null; + try { + input = getClass().getResourceAsStream(file); + prop.load(input); + if (input != null) { + input.close(); + } + } catch (IOException ex) { + log.error("IOException: " + ex); + } + return prop; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/props/PropertySourcesLoader.java b/spring-boot/src/main/java/com/baeldung/servlets/props/PropertySourcesLoader.java new file mode 100644 index 0000000000..56a6751326 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/props/PropertySourcesLoader.java @@ -0,0 +1,23 @@ +package com.baeldung.servlets.props; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.ConfigurableEnvironment; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.*" }) +@PropertySource("classpath:custom.properties") public class PropertySourcesLoader { + + private static final Logger log = LoggerFactory.getLogger(PropertySourcesLoader.class); + + @Autowired + ConfigurableEnvironment env; + + public String getProperty(String key) { + return env.getProperty(key); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/servlets/GenericCustomServlet.java b/spring-boot/src/main/java/com/baeldung/servlets/servlets/GenericCustomServlet.java new file mode 100644 index 0000000000..49dd9404b7 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/servlets/GenericCustomServlet.java @@ -0,0 +1,18 @@ +package com.baeldung.servlets.servlets; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class GenericCustomServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("

Hello World

"); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/servlets/javaee/AnnotationServlet.java b/spring-boot/src/main/java/com/baeldung/servlets/servlets/javaee/AnnotationServlet.java new file mode 100644 index 0000000000..b50a7d5454 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/servlets/javaee/AnnotationServlet.java @@ -0,0 +1,20 @@ +package com.baeldung.servlets.servlets.javaee; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet(name = "AnnotationServlet", + description = "Example Servlet Using Annotations", + urlPatterns = { "/annotationservlet" }) +public class AnnotationServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.getRequestDispatcher("/annotationservlet.jsp").forward(request, response); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/servlets/javaee/EEWebXmlServlet.java b/spring-boot/src/main/java/com/baeldung/servlets/servlets/javaee/EEWebXmlServlet.java new file mode 100644 index 0000000000..c7b373064f --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/servlets/javaee/EEWebXmlServlet.java @@ -0,0 +1,20 @@ +package com.baeldung.servlets.servlets.javaee; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class EEWebXmlServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("

Hello World

"); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/servlets/springboot/SpringRegistrationBeanServlet.java b/spring-boot/src/main/java/com/baeldung/servlets/servlets/springboot/SpringRegistrationBeanServlet.java new file mode 100644 index 0000000000..e3c225d429 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/servlets/springboot/SpringRegistrationBeanServlet.java @@ -0,0 +1,17 @@ +package com.baeldung.servlets.servlets.springboot; + +import com.baeldung.servlets.servlets.GenericCustomServlet; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringRegistrationBeanServlet { + + @Bean + public ServletRegistrationBean genericCustomServlet() { + ServletRegistrationBean bean = new ServletRegistrationBean(new GenericCustomServlet(), "/springregistrationbeanservlet/*"); + bean.setLoadOnStartup(1); + return bean; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/servlets/servlets/springboot/embedded/EmbeddedTomcatExample.java b/spring-boot/src/main/java/com/baeldung/servlets/servlets/springboot/embedded/EmbeddedTomcatExample.java new file mode 100644 index 0000000000..9e460d03a8 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/servlets/servlets/springboot/embedded/EmbeddedTomcatExample.java @@ -0,0 +1,16 @@ +package com.baeldung.servlets.servlets.springboot.embedded; + +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class EmbeddedTomcatExample { + + @Bean + public EmbeddedServletContainerFactory servletContainer() { + TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); + return tomcat; + } +} diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index d30045d1dc..8c6549f53d 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -28,4 +28,8 @@ security.user.name=admin1 security.user.password=secret1 management.security.role=SUPERUSER -logging.level.org.springframework=INFO \ No newline at end of file +logging.level.org.springframework=INFO + +#Servlet Configuration +servlet.name=dispatcherExample +servlet.mapping=/dispatcherExampleURL diff --git a/spring-boot/src/main/resources/custom.properties b/spring-boot/src/main/resources/custom.properties new file mode 100644 index 0000000000..34f31bcd50 --- /dev/null +++ b/spring-boot/src/main/resources/custom.properties @@ -0,0 +1,4 @@ +dispatcher.servlet.name=dispatcherExample +dispatcher.servlet.mapping=/dispatcherExampleURL +example.servlet.name=dispatcherExample +example.servlet.mapping=/dispatcherExampleURL \ No newline at end of file diff --git a/spring-boot/src/main/webapp/WEB-INF/context.xml b/spring-boot/src/main/webapp/WEB-INF/context.xml new file mode 100644 index 0000000000..263bed4430 --- /dev/null +++ b/spring-boot/src/main/webapp/WEB-INF/context.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/spring-boot/src/main/webapp/WEB-INF/dispatcher.xml b/spring-boot/src/main/webapp/WEB-INF/dispatcher.xml new file mode 100644 index 0000000000..ade8e66777 --- /dev/null +++ b/spring-boot/src/main/webapp/WEB-INF/dispatcher.xml @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/spring-boot/src/main/webapp/WEB-INF/web.xml b/spring-boot/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..60a4b079de --- /dev/null +++ b/spring-boot/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,40 @@ + + + JSP + + index.html + index.htm + index.jsp + + + + + EEWebXmlServlet + com.baeldung.servlets.javaee.EEWebXmlServlet + + + + EEWebXmlServlet + /eewebxmlservlet + + + + + SpringBootWebXmlServlet + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/dispatcher.xml + + 1 + + + + SpringBootWebXmlServlet + / + + + + diff --git a/spring-boot/src/main/webapp/annotationservlet.jsp b/spring-boot/src/main/webapp/annotationservlet.jsp new file mode 100644 index 0000000000..f21748df50 --- /dev/null +++ b/spring-boot/src/main/webapp/annotationservlet.jsp @@ -0,0 +1 @@ +

Annotation Servlet!

\ No newline at end of file diff --git a/spring-boot/src/main/webapp/index.jsp b/spring-boot/src/main/webapp/index.jsp new file mode 100644 index 0000000000..e534282777 --- /dev/null +++ b/spring-boot/src/main/webapp/index.jsp @@ -0,0 +1 @@ +

Hello!

\ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/README.MD b/spring-cloud/spring-cloud-bootstrap/README.MD index d6f8faf31e..251c861830 100644 --- a/spring-cloud/spring-cloud-bootstrap/README.MD +++ b/spring-cloud/spring-cloud-bootstrap/README.MD @@ -1,3 +1,12 @@ ### Relevant Articles: - [Spring Cloud – Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping) - [Spring Cloud – Securing Services](http://www.baeldung.com/spring-cloud-securing-services) + +- To run the project: + - copy the appliction-config folder to c:\Users\{username}\ on Windows or /Users/{username}/ on *nix. Then open a git bash terminal in application-config and run: + - git init + - git add . + - git commit -m "First commit" + - start the config server + - start the discover server + - start all the other servers in any order (gateway, svc-book, svc-rating, zipkin) diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties index e1244a0cf0..49f7d1ed91 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties @@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug spring.redis.host=localhost spring.redis.port=6379 + +spring.sleuth.sampler.percentage=1.0 +spring.sleuth.web.skipPattern=(^cleanup.*) diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties index 09f7f3bf4a..e9e593284c 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties @@ -24,4 +24,7 @@ logging.level.org.springframework.security=debug logging.level.org.springframework.cloud.netflix.zuul=debug spring.redis.host=localhost -spring.redis.port=6379 \ No newline at end of file +spring.redis.port=6379 + +spring.sleuth.sampler.percentage=1.0 +spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*) \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties index 4817d12c83..b7cbb6fbd6 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties @@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug spring.redis.host=localhost spring.redis.port=6379 + +spring.sleuth.sampler.percentage=1.0 +spring.sleuth.web.skipPattern=(^cleanup.*) diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties b/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties new file mode 100644 index 0000000000..ca3aed2263 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties @@ -0,0 +1,7 @@ +spring.application.name=zipkin +server.port=9411 + +eureka.client.region = default +eureka.client.registryFetchIntervalSeconds = 5 + +logging.level.org.springframework.web=debug diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml index 044730ba22..13ae6b4050 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml @@ -41,11 +41,23 @@ spring-boot-starter-data-redis
+ + org.springframework.cloud + spring-cloud-starter-zipkin + + org.springframework.boot spring-boot-starter-test test + + + io.rest-assured + rest-assured + test + 3.0.2 + diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java index b5ae1e4e7b..16aae66cab 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java @@ -1,6 +1,9 @@ package com.baeldung.spring.cloud.bootstrap.gateway; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; @@ -8,8 +11,13 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; +import org.springframework.cloud.sleuth.metric.SpanMetricReporter; +import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; +import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; +import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; +import zipkin.Span; import java.util.ArrayList; import java.util.List; @@ -18,23 +26,50 @@ import java.util.List; @EnableZuulProxy @EnableEurekaClient public class GatewayApplication { - public static void main(String[] args) { - SpringApplication.run(GatewayApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class, args); + } - @Autowired(required = false) - private List configurations = new ArrayList<>(); + @Autowired(required = false) + private List configurations = new ArrayList<>(); + @Autowired + private EurekaClient eurekaClient; + @Autowired + private SpanMetricReporter spanMetricReporter; + @Autowired + private ZipkinProperties zipkinProperties; + @Value("${spring.sleuth.web.skipPattern}") + private String skipPattern; - @Bean - @LoadBalanced - RestTemplate restTemplate() { - return new RestTemplate(); - } + @Bean + @LoadBalanced + RestTemplate restTemplate() { + return new RestTemplate(); + } - @Bean - public SpringClientFactory springClientFactory() { - SpringClientFactory factory = new SpringClientFactory(); - factory.setConfigurations(this.configurations); - return factory; - } + @Bean + public SpringClientFactory springClientFactory() { + SpringClientFactory factory = new SpringClientFactory(); + factory.setConfigurations(this.configurations); + return factory; + } + + @Bean + public ZipkinSpanReporter makeZipkinSpanReporter() { + return new ZipkinSpanReporter() { + private HttpZipkinSpanReporter delegate; + private String baseUrl; + + @Override + public void report(Span span) { + InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); + if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) { + baseUrl = instance.getHomePageUrl(); + delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter); + if (!span.name.matches(skipPattern)) delegate.report(span); + } + if (!span.name.matches(skipPattern)) delegate.report(span); + } + }; + } } diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java index 9e5c424403..935e50ec72 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java @@ -23,6 +23,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/book-service/books").permitAll() + .antMatchers("/zipkin/**").permitAll() .antMatchers("/eureka/**").hasRole("ADMIN") .anyRequest().authenticated() .and() diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java new file mode 100644 index 0000000000..71ed2cd709 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/LiveTest.java @@ -0,0 +1,198 @@ +package com.baeldung.spring.cloud.bootstrap.gateway; + +import static io.restassured.RestAssured.config; +import io.restassured.RestAssured; +import io.restassured.authentication.FormAuthConfig; +import io.restassured.config.RedirectConfig; +import io.restassured.http.ContentType; +import io.restassured.response.Response; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpStatus; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +public class LiveTest { + + private final String ROOT_URI = "http://localhost:8080"; + private final FormAuthConfig formConfig = new FormAuthConfig("/login", "username", "password"); + + @Before + public void setup() { + RestAssured.config = config().redirect(RedirectConfig.redirectConfig() + .followRedirects(false)); + } + + @Test + public void whenGetAllBooks_thenSuccess() { + final Response response = RestAssured.get(ROOT_URI + "/book-service/books"); + Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + } + + @Test + public void whenAccessProtectedResourceWithoutLogin_thenRedirectToLogin() { + final Response response = RestAssured.get(ROOT_URI + "/book-service/books/1"); + Assert.assertEquals(HttpStatus.FOUND.value(), response.getStatusCode()); + Assert.assertEquals("http://localhost:8080/login", response.getHeader("Location")); + } + + @Test + public void whenAccessProtectedResourceAfterLogin_thenSuccess() { + final Response response = RestAssured.given() + .auth() + .form("user", "password", formConfig) + .get(ROOT_URI + "/book-service/books/1"); + Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + } + + @Test + public void whenAccessAdminProtectedResource_thenForbidden() { + final Response response = RestAssured.given() + .auth() + .form("user", "password", formConfig) + .get(ROOT_URI + "/rating-service/ratings"); + Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getStatusCode()); + + } + + @Test + public void whenAdminAccessProtectedResource_thenSuccess() { + final Response response = RestAssured.given() + .auth() + .form("admin", "admin", formConfig) + .get(ROOT_URI + "/rating-service/ratings"); + Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + } + + @Test + public void whenAdminAccessDiscoveryResource_thenSuccess() { + final Response response = RestAssured.given() + .auth() + .form("admin", "admin", formConfig) + .get(ROOT_URI + "/discovery"); + Assert.assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + } + + @Test + public void whenAddnewRating_thenSuccess() { + + final Rating rating = new Rating(1L, 4); + + // request the protected resource + final Response ratingResponse = RestAssured.given() + .auth() + .form("admin", "admin", formConfig) + .and() + .contentType(ContentType.JSON) + .body(rating) + .post(ROOT_URI + "/rating-service/ratings"); + final Rating result = ratingResponse.as(Rating.class); + Assert.assertEquals(HttpStatus.OK.value(), ratingResponse.getStatusCode()); + Assert.assertEquals(rating.getBookId(), result.getBookId()); + Assert.assertEquals(rating.getStars(), result.getStars()); + } + + @Test + public void whenAddnewBook_thenSuccess() { + final Book book = new Book("Baeldung", "How to spring cloud"); + + // request the protected resource + final Response bookResponse = RestAssured.given() + .auth() + .form("admin", "admin", formConfig) + .and() + .contentType(ContentType.JSON) + .body(book) + .post(ROOT_URI + "/book-service/books"); + final Book result = bookResponse.as(Book.class); + Assert.assertEquals(HttpStatus.OK.value(), bookResponse.getStatusCode()); + Assert.assertEquals(book.getAuthor(), result.getAuthor()); + Assert.assertEquals(book.getTitle(), result.getTitle()); + + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Book { + + private Long id; + private String author; + private String title; + + public Book() { + } + + public Book(String author, String title) { + this.author = author; + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Rating { + private Long id; + private Long bookId; + private int stars; + + public Rating() { + } + + public Rating(Long bookId, int stars) { + this.bookId = bookId; + this.stars = stars; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getBookId() { + return bookId; + } + + public void setBookId(Long bookId) { + this.bookId = bookId; + } + + public int getStars() { + return stars; + } + + public void setStars(int stars) { + this.stars = stars; + } + } + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/pom.xml b/spring-cloud/spring-cloud-bootstrap/pom.xml index ccfbdb9735..83879cf7d4 100644 --- a/spring-cloud/spring-cloud-bootstrap/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/pom.xml @@ -16,6 +16,7 @@ gateway svc-book svc-rating + zipkin diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml index c351c444f6..cbf7083b83 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml @@ -53,6 +53,11 @@ runtime + + org.springframework.cloud + spring-cloud-starter-zipkin + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java index c5499cd924..3d55a59dbc 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java @@ -1,13 +1,51 @@ package com.baeldung.spring.cloud.bootstrap.svcbook; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.sleuth.metric.SpanMetricReporter; +import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; +import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; +import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; +import org.springframework.context.annotation.Bean; +import zipkin.Span; @SpringBootApplication @EnableEurekaClient public class BookServiceApplication { + + @Autowired + private EurekaClient eurekaClient; + @Autowired + private SpanMetricReporter spanMetricReporter; + @Autowired + private ZipkinProperties zipkinProperties; + @Value("${spring.sleuth.web.skipPattern}") + private String skipPattern; + public static void main(String[] args) { SpringApplication.run(BookServiceApplication.class, args); } + + @Bean + public ZipkinSpanReporter makeZipkinSpanReporter() { + return new ZipkinSpanReporter() { + private HttpZipkinSpanReporter delegate; + private String baseUrl; + + @Override + public void report(Span span) { + InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); + if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) { + baseUrl = instance.getHomePageUrl(); + delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter); + if (!span.name.matches(skipPattern)) delegate.report(span); + } + } + }; + } } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties index 8f3a3261ac..481cdc182c 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties @@ -4,4 +4,4 @@ spring.cloud.config.discovery.enabled=true spring.cloud.config.username=configUser spring.cloud.config.password=configPassword -eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ +eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml index 2285286812..f02ba88f04 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml @@ -53,6 +53,11 @@ runtime + + org.springframework.cloud + spring-cloud-starter-zipkin + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java index 61074e0bcc..0d85c5c825 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java @@ -1,13 +1,51 @@ package com.baeldung.spring.cloud.bootstrap.svcrating; +import com.netflix.appinfo.InstanceInfo; +import com.netflix.discovery.EurekaClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.sleuth.metric.SpanMetricReporter; +import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter; +import org.springframework.cloud.sleuth.zipkin.ZipkinProperties; +import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter; +import org.springframework.context.annotation.Bean; +import zipkin.Span; @SpringBootApplication @EnableEurekaClient public class RatingServiceApplication { + @Autowired + private EurekaClient eurekaClient; + @Autowired + private SpanMetricReporter spanMetricReporter; + @Autowired + private ZipkinProperties zipkinProperties; + @Value("${spring.sleuth.web.skipPattern}") + private String skipPattern; + public static void main(String[] args) { SpringApplication.run(RatingServiceApplication.class, args); } + + @Bean + public ZipkinSpanReporter makeZipkinSpanReporter() { + return new ZipkinSpanReporter() { + private HttpZipkinSpanReporter delegate; + private String baseUrl; + + @Override + public void report(Span span) { + InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false); + if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) { + baseUrl = instance.getHomePageUrl(); + delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter); + if (!span.name.matches(skipPattern)) delegate.report(span); + } + if (!span.name.matches(skipPattern)) delegate.report(span); + } + }; + } } \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml new file mode 100644 index 0000000000..c2fd7cd2dc --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + zipkin + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.4.RELEASE + + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-eureka + + + + io.zipkin.java + zipkin-server + + + + io.zipkin.java + zipkin-autoconfigure-ui + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*LiveTest.java + + + + + + + + Brixton.SR7 + 3.6.0 + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java new file mode 100644 index 0000000000..d757567156 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.bootstrap.zipkin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import zipkin.server.EnableZipkinServer; + +@SpringBootApplication +@EnableEurekaClient +@EnableZipkinServer +public class ZipkinApplication { + public static void main(String[] args) { + SpringApplication.run(ZipkinApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..9569179a4f --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties @@ -0,0 +1,7 @@ +spring.cloud.config.name=zipkin +spring.cloud.config.discovery.service-id=config +spring.cloud.config.discovery.enabled=true +spring.cloud.config.username=configUser +spring.cloud.config.password=configPassword + +eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-core/src/main/java/com/baeldung/Ebook.java b/spring-core/src/main/java/com/baeldung/Ebook.java new file mode 100644 index 0000000000..fc29ddfcf5 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/Ebook.java @@ -0,0 +1,20 @@ +package com.baeldung; + +public class Ebook { + + private int bookId; + private String bookTitle; + + public int getBookId() { + return bookId; + } + public void setBookId(int bookId) { + this.bookId = bookId; + } + public String getBookTitle() { + return bookTitle; + } + public void setBookTitle(String bookTitle) { + this.bookTitle = bookTitle; + } +} diff --git a/spring-core/src/main/java/com/baeldung/EbookRepository.java b/spring-core/src/main/java/com/baeldung/EbookRepository.java new file mode 100644 index 0000000000..661283c355 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/EbookRepository.java @@ -0,0 +1,5 @@ +package com.baeldung; + +public interface EbookRepository { + String titleById(int id); +} diff --git a/spring-core/src/main/java/com/baeldung/LibraryUtils.java b/spring-core/src/main/java/com/baeldung/LibraryUtils.java new file mode 100644 index 0000000000..49af60c89d --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/LibraryUtils.java @@ -0,0 +1,12 @@ +package com.baeldung; + +import org.springframework.beans.factory.annotation.Autowired; + +public class LibraryUtils { + @Autowired + private EbookRepository eBookRepository; + + public String findBook(int id) { + return eBookRepository.titleById(id); + } +} diff --git a/spring-core/src/main/java/com/baeldung/Member.java b/spring-core/src/main/java/com/baeldung/Member.java new file mode 100644 index 0000000000..ceebb32017 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/Member.java @@ -0,0 +1,20 @@ +package com.baeldung; + +public class Member { + + private int memberId; + private String memberName; + + public int getMemberId() { + return memberId; + } + public void setMemberId(int memberId) { + this.memberId = memberId; + } + public String getMemberName() { + return memberName; + } + public void setMemberName(String memberName) { + this.memberName = memberName; + } +} diff --git a/spring-core/src/main/java/com/baeldung/Reservation.java b/spring-core/src/main/java/com/baeldung/Reservation.java new file mode 100644 index 0000000000..ed33bb6464 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/Reservation.java @@ -0,0 +1,14 @@ +package com.baeldung; + +import org.springframework.beans.factory.annotation.Autowired; + +public class Reservation { + private Member member; + private Ebook eBook; + + @Autowired + public Reservation(Member member, Ebook eBook) { + this.member = member; + this.eBook = eBook; + } +} diff --git a/spring-data-mongodb/README.md b/spring-data-mongodb/README.md index d656bc897c..c2a1f703b5 100644 --- a/spring-data-mongodb/README.md +++ b/spring-data-mongodb/README.md @@ -9,3 +9,4 @@ - [Custom Cascading in Spring Data MongoDB](http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb) - [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) - [Introduction to Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-tutorial) +- [Spring Data MongoDB: Projections and Aggregations](http://www.baeldung.com/spring-data-mongodb-projections-aggregations) diff --git a/spring-data-neo4j/README.md b/spring-data-neo4j/README.md index 0f13d9dbc9..03c9ed333d 100644 --- a/spring-data-neo4j/README.md +++ b/spring-data-neo4j/README.md @@ -2,6 +2,7 @@ ### Relevant Articles: - [Introduction to Spring Data Neo4j](http://www.baeldung.com/spring-data-neo4j-intro) +- [A Guide to Neo4J with Java](http://www.baeldung.com/java-neo4j) ### Build the Project with Tests Running ``` diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md index 4e8828a688..f77c4dc202 100644 --- a/spring-data-rest/README.md +++ b/spring-data-rest/README.md @@ -15,3 +15,4 @@ To view the running application, visit [http://localhost:8080](http://localhost: ###Relevant Articles: - [Guide to Spring Data REST Validators](http://www.baeldung.com/spring-data-rest-validators) +- [Working with Relationships in Spring Data REST](http://www.baeldung.com/spring-data-rest-relationships) diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml index 4e8001ae7b..1845d60e94 100644 --- a/spring-data-rest/pom.xml +++ b/spring-data-rest/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.4.RELEASE + 1.5.1.RELEASE diff --git a/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..bed1a6f846 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java @@ -0,0 +1,25 @@ +package com.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter{ + + public MvcConfig(){ + super(); + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Address.java b/spring-data-rest/src/main/java/com/baeldung/models/Address.java new file mode 100644 index 0000000000..98cf5f0869 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/models/Address.java @@ -0,0 +1,53 @@ +package com.baeldung.models; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToOne; + +@Entity +public class Address { + + @Id + @GeneratedValue + private long id; + + @Column(nullable = false) + private String location; + + @OneToOne(mappedBy = "address") + private Library library; + + public Address() { + } + + public Address(String location) { + super(); + this.location = location; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public Library getLibrary() { + return library; + } + + public void setLibrary(Library library) { + this.library = library; + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Author.java b/spring-data-rest/src/main/java/com/baeldung/models/Author.java new file mode 100644 index 0000000000..7025fa4ad3 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/models/Author.java @@ -0,0 +1,59 @@ +package com.baeldung.models; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; + +@Entity +public class Author { + + @Id + @GeneratedValue + private long id; + + @Column(nullable = false) + private String name; + + @ManyToMany(cascade = CascadeType.ALL) + @JoinTable(name = "book_author", joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "author_id", referencedColumnName = "id")) + private List books; + + public Author() { + } + + public Author(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Book.java b/spring-data-rest/src/main/java/com/baeldung/models/Book.java new file mode 100644 index 0000000000..8f836a259a --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/models/Book.java @@ -0,0 +1,70 @@ +package com.baeldung.models; + +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; + +@Entity +public class Book { + + @Id + @GeneratedValue + private long id; + + @Column(nullable = false) + private String title; + + @ManyToOne + @JoinColumn(name = "library_id") + private Library library; + + @ManyToMany(mappedBy = "books") + private List authors; + + public Book() { + } + + public Book(String title) { + super(); + this.title = title; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Library getLibrary() { + return library; + } + + public void setLibrary(Library library) { + this.library = library; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(List authors) { + this.authors = authors; + } + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Library.java b/spring-data-rest/src/main/java/com/baeldung/models/Library.java new file mode 100644 index 0000000000..61eead16ea --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/models/Library.java @@ -0,0 +1,73 @@ +package com.baeldung.models; + +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; + +import org.springframework.data.rest.core.annotation.RestResource; + +@Entity +public class Library { + + @Id + @GeneratedValue + private long id; + + @Column + private String name; + + @OneToOne + @JoinColumn(name = "address_id") + @RestResource(path = "libraryAddress") + private Address address; + + @OneToMany(mappedBy = "library") + private List books; + + public Library() { + } + + public Library(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/AddressRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/AddressRepository.java new file mode 100644 index 0000000000..1cc7527e80 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/AddressRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.repositories; + +import org.springframework.data.repository.CrudRepository; + +import com.baeldung.models.Address; + +public interface AddressRepository extends CrudRepository { + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/AuthorRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/AuthorRepository.java new file mode 100644 index 0000000000..2d470367ef --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/AuthorRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.repositories; + +import org.springframework.data.repository.CrudRepository; + +import com.baeldung.models.Author; + +public interface AuthorRepository extends CrudRepository { + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java new file mode 100644 index 0000000000..f9176032ab --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.repositories; + +import org.springframework.data.repository.CrudRepository; + +import com.baeldung.models.Book; + +public interface BookRepository extends CrudRepository { + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/LibraryRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/LibraryRepository.java new file mode 100644 index 0000000000..c00787f03c --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/LibraryRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.repositories; + +import org.springframework.data.repository.CrudRepository; + +import com.baeldung.models.Library; + +public interface LibraryRepository extends CrudRepository { + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java index 0b55ac89b6..2bd9c025dd 100644 --- a/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java @@ -2,9 +2,10 @@ package com.baeldung.repositories; import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; - +import org.springframework.web.bind.annotation.CrossOrigin; import com.baeldung.models.WebsiteUser; +@CrossOrigin @RepositoryRestResource(collectionResourceRel = "users", path = "users") public interface UserRepository extends CrudRepository { diff --git a/spring-data-rest/src/main/webapp/users.html b/spring-data-rest/src/main/webapp/users.html new file mode 100644 index 0000000000..c153f4a36e --- /dev/null +++ b/spring-data-rest/src/main/webapp/users.html @@ -0,0 +1,51 @@ + + + + +User CRUD + + + + + +
+ + + + + + + + + + + + + +
ID:
Name:
Email:
+

+ Get User + Update User + Add User + Delete User + +

+

{{message}}

+

{{errorMessage}}

+ +
+
+ Get all Users
+

+
+ {{usr.name}} {{usr.email}} +
+
+ + \ No newline at end of file diff --git a/spring-data-rest/src/main/webapp/view/app.js b/spring-data-rest/src/main/webapp/view/app.js new file mode 100644 index 0000000000..0bdc6e1979 --- /dev/null +++ b/spring-data-rest/src/main/webapp/view/app.js @@ -0,0 +1,122 @@ +var app = angular.module('app',[]); + +app.controller('UserCRUDCtrl', ['$scope','UserCRUDService', function ($scope,UserCRUDService) { + + $scope.updateUser = function () { + UserCRUDService.updateUser($scope.user.id,$scope.user.name,$scope.user.email) + .then(function success(response){ + $scope.message = 'User data updated!'; + $scope.errorMessage = ''; + }, + function error(response){ + $scope.errorMessage = 'Error updating user!'; + $scope.message = ''; + }); + } + + $scope.getUser = function () { + var id = $scope.user.id; + UserCRUDService.getUser($scope.user.id) + .then(function success(response){ + $scope.user = response.data; + $scope.user.id = id; + $scope.message=''; + $scope.errorMessage = ''; + }, + function error (response ){ + $scope.message = ''; + if (response.status === 404){ + $scope.errorMessage = 'User not found!'; + } + else { + $scope.errorMessage = "Error getting user!"; + } + }); + } + + $scope.addUser = function () { + if ($scope.user != null && $scope.user.name) { + UserCRUDService.addUser($scope.user.name, $scope.user.email) + .then (function success(response){ + $scope.message = 'User added!'; + $scope.errorMessage = ''; + }, + function error(response){ + $scope.errorMessage = 'Error adding user!'; + $scope.message = ''; + }); + } + else { + $scope.errorMessage = 'Please enter a name!'; + $scope.message = ''; + } + } + + $scope.deleteUser = function () { + UserCRUDService.deleteUser($scope.user.id) + .then (function success(response){ + $scope.message = 'User deleted!'; + $scope.user = null; + $scope.errorMessage=''; + }, + function error(response){ + $scope.errorMessage = 'Error deleting user!'; + $scope.message=''; + }) + } + + $scope.getAllUsers = function () { + UserCRUDService.getAllUsers() + .then(function success(response){ + $scope.users = response.data._embedded.users; + $scope.message=''; + $scope.errorMessage = ''; + }, + function error (response ){ + $scope.message=''; + $scope.errorMessage = 'Error getting users!'; + }); + } + +}]); + +app.service('UserCRUDService',['$http', function ($http) { + + this.getUser = function getUser(userId){ + return $http({ + method: 'GET', + url: 'users/'+userId + }); + } + + this.addUser = function addUser(name, email){ + return $http({ + method: 'POST', + url: 'users', + data: {name:name, email:email} + }); + } + + this.deleteUser = function deleteUser(id){ + return $http({ + method: 'DELETE', + url: 'users/'+id + }) + } + + this.updateUser = function updateUser(id,name,email){ + return $http({ + method: 'PATCH', + url: 'users/'+id, + data: {name:name, email:email} + }) + } + + this.getAllUsers = function getAllUsers(){ + return $http({ + method: 'GET', + url: 'users' + }); + } + +}]); \ No newline at end of file diff --git a/spring-data-rest/src/test/java/com/baeldung/relationships/SpringDataRelationshipsTest.java b/spring-data-rest/src/test/java/com/baeldung/relationships/SpringDataRelationshipsTest.java new file mode 100644 index 0000000000..43b5dd7da6 --- /dev/null +++ b/spring-data-rest/src/test/java/com/baeldung/relationships/SpringDataRelationshipsTest.java @@ -0,0 +1,102 @@ +package com.baeldung.relationships; + +import com.baeldung.SpringDataRestApplication; +import com.baeldung.models.Address; +import com.baeldung.models.Author; +import com.baeldung.models.Book; +import com.baeldung.models.Library; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import org.json.JSONException; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringDataRestApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT) +public class SpringDataRelationshipsTest { + + @Autowired + private TestRestTemplate template; + + private static final String BOOK_ENDPOINT = "http://localhost:8080/books/"; + private static final String AUTHOR_ENDPOINT = "http://localhost:8080/authors/"; + private static final String ADDRESS_ENDPOINT = "http://localhost:8080/addresses/"; + private static final String LIBRARY_ENDPOINT = "http://localhost:8080/libraries/"; + + private static final String LIBRARY_NAME = "My Library"; + private static final String AUTHOR_NAME = "George Orwell"; + + @Test + public void whenSaveOneToOneRelationship_thenCorrect() throws JSONException { + Library library = new Library(LIBRARY_NAME); + template.postForEntity(LIBRARY_ENDPOINT, library, Library.class); + + Address address = new Address("Main street, nr 1"); + template.postForEntity(ADDRESS_ENDPOINT, address, Address.class); + + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.add("Content-type", "text/uri-list"); + HttpEntity httpEntity = new HttpEntity<>(ADDRESS_ENDPOINT + "/1", requestHeaders); + template.exchange(LIBRARY_ENDPOINT + "/1/libraryAddress", HttpMethod.PUT, httpEntity, String.class); + + ResponseEntity libraryGetResponse = template.getForEntity(ADDRESS_ENDPOINT + "/1/library", Library.class); + assertEquals("library is incorrect", libraryGetResponse.getBody() + .getName(), LIBRARY_NAME); + } + + @Test + public void whenSaveOneToManyRelationship_thenCorrect() throws JSONException{ + Library library = new Library(LIBRARY_NAME); + template.postForEntity(LIBRARY_ENDPOINT, library, Library.class); + + Book book1 = new Book("Dune"); + template.postForEntity(BOOK_ENDPOINT, book1, Book.class); + + Book book2 = new Book("1984"); + template.postForEntity(BOOK_ENDPOINT, book2, Book.class); + + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.add("Content-type", "text/uri-list"); + HttpEntity bookHttpEntity = new HttpEntity<>(LIBRARY_ENDPOINT + "/1", requestHeaders); + template.exchange(BOOK_ENDPOINT + "/1/library", HttpMethod.PUT, bookHttpEntity, String.class); + template.exchange(BOOK_ENDPOINT + "/2/library", HttpMethod.PUT, bookHttpEntity, String.class); + + ResponseEntity libraryGetResponse = template.getForEntity(BOOK_ENDPOINT + "/1/library", Library.class); + assertEquals("library is incorrect", libraryGetResponse.getBody() + .getName(), LIBRARY_NAME); + } + + @Test + public void whenSaveManyToManyRelationship_thenCorrect() throws JSONException{ + Author author1 = new Author(AUTHOR_NAME); + template.postForEntity(AUTHOR_ENDPOINT, author1, Author.class); + + Book book1 = new Book("Animal Farm"); + template.postForEntity(BOOK_ENDPOINT, book1, Book.class); + + Book book2 = new Book("1984"); + template.postForEntity(BOOK_ENDPOINT, book2, Book.class); + + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.add("Content-type", "text/uri-list"); + HttpEntity httpEntity = new HttpEntity<>(BOOK_ENDPOINT + "/1\n" + BOOK_ENDPOINT + "/2", requestHeaders); + template.exchange(AUTHOR_ENDPOINT + "/1/books", HttpMethod.PUT, httpEntity, String.class); + + String jsonResponse = template.getForObject(BOOK_ENDPOINT + "/1/authors", String.class); + JSONObject jsonObj = new JSONObject(jsonResponse).getJSONObject("_embedded"); + JSONArray jsonArray = jsonObj.getJSONArray("authors"); + assertEquals("author is incorrect", jsonArray.getJSONObject(0) + .getString("name"), AUTHOR_NAME); + } +} diff --git a/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java b/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorTest.java similarity index 75% rename from spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java rename to spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorTest.java index b185c6d5ab..300fc081d3 100644 --- a/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorTest.java @@ -1,100 +1,86 @@ -package com.baeldung.validator; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.ResultMatcher; -import org.springframework.web.context.WebApplicationContext; - -import com.baeldung.SpringDataRestApplication; -import com.baeldung.models.WebsiteUser; -import com.fasterxml.jackson.databind.ObjectMapper; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringDataRestApplication.class) -@WebAppConfiguration -public class SpringDataRestValidatorTest { - public static final String URL = "http://localhost"; - - private MockMvc mockMvc; - - @Autowired - protected WebApplicationContext wac; - - @Before - public void setup() { - mockMvc = webAppContextSetup(wac).build(); - } - - @Test - public void whenStartingApplication_thenCorrectStatusCode() throws Exception { - mockMvc.perform(get("/users")).andExpect(status().is2xxSuccessful()); - }; - - @Test - public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setEmail("john.doe@john.com"); - user.setName("John Doe"); - - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().is2xxSuccessful()) - .andExpect(redirectedUrl("http://localhost/users/1")); - } - - @Test - public void whenAddingNewUserWithoutName_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setEmail("john.doe@john.com"); - - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - - @Test - public void whenAddingNewUserWithEmptyName_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setEmail("john.doe@john.com"); - user.setName(""); - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - - @Test - public void whenAddingNewUserWithoutEmail_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setName("John Doe"); - - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - - @Test - public void whenAddingNewUserWithEmptyEmail_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setName("John Doe"); - user.setEmail(""); - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - -} +package com.baeldung.validator; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.SpringDataRestApplication; +import com.baeldung.models.WebsiteUser; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = SpringDataRestApplication.class) +@WebAppConfiguration +public class SpringDataRestValidatorTest { + public static final String URL = "http://localhost"; + + private MockMvc mockMvc; + + @Autowired + protected WebApplicationContext wac; + + @Before + public void setup() { + mockMvc = webAppContextSetup(wac).build(); + } + + @Test + public void whenStartingApplication_thenCorrectStatusCode() throws Exception { + mockMvc.perform(get("/users")).andExpect(status().is2xxSuccessful()); + }; + + @Test + public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().is2xxSuccessful()).andExpect(redirectedUrl("http://localhost/users/1")); + } + + @Test + public void whenAddingNewUserWithoutName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithoutEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + user.setEmail(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + +} diff --git a/spring-data-solr/pom.xml b/spring-data-solr/pom.xml index 2aa9f86a96..e43b3ff774 100644 --- a/spring-data-solr/pom.xml +++ b/spring-data-solr/pom.xml @@ -51,12 +51,6 @@ ${spring.version} test
- diff --git a/spring-data-solr/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java b/spring-data-solr/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java deleted file mode 100644 index ce90ccaf16..0000000000 --- a/spring-data-solr/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.baeldung.solrjava; - -import static org.junit.Assert.assertEquals; - -import java.io.IOException; - -import org.apache.solr.client.solrj.SolrQuery; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpSolrClient; -import org.apache.solr.client.solrj.impl.XMLResponseParser; -import org.apache.solr.client.solrj.response.QueryResponse; -import org.apache.solr.common.SolrDocument; -import org.apache.solr.common.SolrDocumentList; -import org.apache.solr.common.SolrInputDocument; -import org.junit.Before; -import org.junit.Test; - -public class SolrJavaIntegrationTest { - - private HttpSolrClient solr; - private SolrInputDocument document; - - @Before - public void setUp() throws Exception { - - solr = new HttpSolrClient("http://localhost:8983/solr/bigboxstore"); - solr.setParser(new XMLResponseParser()); - - document = new SolrInputDocument(); - document.addField("id", "123456"); - document.addField("name", "Kenmore Dishwasher"); - document.addField("price", "599.99"); - solr.add(document); - solr.commit(); - } - - @Test - public void whenAdd_thenVerifyAdded() throws SolrServerException, IOException { - - SolrQuery query = new SolrQuery(); - query.set("q", "id:123456"); - QueryResponse response = null; - - response = solr.query(query); - - SolrDocumentList docList = response.getResults(); - assertEquals(docList.getNumFound(), 1); - - for (SolrDocument doc : docList) { - assertEquals((String) doc.getFieldValue("id"), "123456"); - assertEquals((Double) doc.getFieldValue("price"), (Double) 599.99); - } - } - - @Test - public void whenDelete_thenVerifyDeleted() throws SolrServerException, IOException { - - solr.deleteById("123456"); - solr.commit(); - - SolrQuery query = new SolrQuery(); - query.set("q", "id:123456"); - QueryResponse response = null; - - response = solr.query(query); - - SolrDocumentList docList = response.getResults(); - assertEquals(docList.getNumFound(), 0); - } -} diff --git a/spring-hibernate4/README.md b/spring-hibernate4/README.md index 7888e8b4ee..02888c4ad0 100644 --- a/spring-hibernate4/README.md +++ b/spring-hibernate4/README.md @@ -12,6 +12,7 @@ - [Hibernate: save, persist, update, merge, saveOrUpdate](http://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate/) - [Eager/Lazy Loading In Hibernate](http://www.baeldung.com/hibernate-lazy-eager-loading) - [Hibernate Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) +- [Hibernate One to Many Annotation Tutorial](http://www.baeldung.com/hibernate-one-to-many) ### Quick Start @@ -22,3 +23,4 @@ mvn install mvn cargo:run ``` - **note**: starts on port `8082` + diff --git a/spring-hibernate5/.gitignore b/spring-hibernate5/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-hibernate5/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-hibernate5/pom.xml b/spring-hibernate5/pom.xml new file mode 100644 index 0000000000..81f8084d74 --- /dev/null +++ b/spring-hibernate5/pom.xml @@ -0,0 +1,239 @@ + + 4.0.0 + com.baeldung + spring-hibernate5 + 0.1-SNAPSHOT + + spring-hibernate5 + + + + + + + org.springframework + spring-context + ${org.springframework.version} + + + org.springframework + spring-aspects + ${org.springframework.version} + + + org.springframework.security + spring-security-core + ${org.springframework.security.version} + + + + + + org.springframework + spring-orm + ${org.springframework.version} + + + org.springframework.data + spring-data-jpa + ${org.springframework.data.version} + + + org.hibernate + hibernate-core + ${hibernate.version} + + + org.hibernate + hibernate-envers + ${hibernate-envers.version} + + + javax.transaction + jta + ${jta.version} + + + mysql + mysql-connector-java + ${mysql-connector-java.version} + + + + org.apache.tomcat + tomcat-dbcp + ${tomcat-dbcp.version} + + + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + javax.el + javax.el-api + ${javax.el-api.version} + + + + + + com.google.guava + guava + ${guava.version} + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + test + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + + junit + junit + ${junit.version} + test + + + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + + + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + + junit + junit-dep + 4.11 + test + + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.hsqldb + hsqldb + ${hsqldb.version} + test + + + + + + spring-hibernate5 + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + + + + + + + + + + + + + + 4.3.5.RELEASE + 4.2.1.RELEASE + 1.10.6.RELEASE + + + 5.2.8.Final + ${hibernate.version} + 6.0.5 + 8.5.11 + 1.1 + 2.3.4 + + + 1.7.21 + 1.1.7 + + + 5.4.0.Final + 2.2.5 + + + 21.0 + 3.5 + + + 1.3 + 4.12 + 2.6.8 + + 4.4.1 + 4.5 + + 2.9.0 + + + 3.6.0 + 2.19.1 + 2.7 + 1.6.1 + + + + diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java new file mode 100644 index 0000000000..957207b7e6 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java @@ -0,0 +1,81 @@ +package com.baeldung.hibernate.criteria.model; + +import java.io.Serializable; + +public class Item implements Serializable { + + private static final long serialVersionUID = 1L; + private Integer itemId; + private String itemName; + private String itemDescription; + private Integer itemPrice; + + // constructors + public Item() { + + } + + public Item(final Integer itemId, final String itemName, final String itemDescription) { + super(); + this.itemId = itemId; + this.itemName = itemName; + this.itemDescription = itemDescription; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Item other = (Item) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (!itemId.equals(other.itemId)) + return false; + return true; + } + + public Integer getItemId() { + return itemId; + } + + public void setItemId(final Integer itemId) { + this.itemId = itemId; + } + + public String getItemName() { + return itemName; + } + + public void setItemName(final String itemName) { + this.itemName = itemName; + } + + public String getItemDescription() { + return itemDescription; + } + + public Integer getItemPrice() { + return itemPrice; + } + + public void setItemPrice(final Integer itemPrice) { + this.itemPrice = itemPrice; + } + + public void setItemDescription(final String itemDescription) { + this.itemDescription = itemDescription; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java new file mode 100644 index 0000000000..9024ba9e4b --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java @@ -0,0 +1,17 @@ +package com.baeldung.hibernate.criteria.util; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; + +public class HibernateUtil { + + public static Session getHibernateSession() { + + final SessionFactory sf = new Configuration().configure("criteria.cfg.xml").buildSessionFactory(); + + final Session session = sf.openSession(); + return session; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java new file mode 100644 index 0000000000..a854b51753 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java @@ -0,0 +1,284 @@ +/** + * ApplicationViewer is the class that starts the application + * First it creates the session object and then creates the + * criteria query. + * + * @author Sandeep Kumar + * @version 1.0 + * @since 01/13/2017 + */ + +package com.baeldung.hibernate.criteria.view; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.hibernate.Session; +import org.hibernate.Transaction; + +import com.baeldung.hibernate.criteria.model.Item; +import com.baeldung.hibernate.criteria.util.HibernateUtil; + +public class ApplicationView { + + public ApplicationView() { + + } + + @SuppressWarnings("unchecked") + public boolean checkIfCriteriaTimeLower() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + Transaction tx = null; + + // calculate the time taken by criteria + final long startTimeCriteria = System.nanoTime(); + criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%item One%")); + final List results = session.createQuery(criteriaItem).getResultList(); + final long endTimeCriteria = System.nanoTime(); + final long durationCriteria = (endTimeCriteria - startTimeCriteria) / 1000; + + // calculate the time taken by HQL + final long startTimeHQL = System.nanoTime(); + tx = session.beginTransaction(); + final List items = session.createQuery("FROM Item where itemName like '%item One%'").getResultList(); + final long endTimeHQL = System.nanoTime(); + final long durationHQL = (endTimeHQL - startTimeHQL) / 1000; + + if (durationCriteria > durationHQL) { + return false; + } else { + return true; + } + } + + // To get items having price more than 1000 + public String[] greaterThanCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.greaterThan(rootItem.get("itemPrice"), 1000)); + final List greaterThanItemsList = session.createQuery(criteriaItem).getResultList(); + final String greaterThanItems[] = new String[greaterThanItemsList.size()]; + for (int i = 0; i < greaterThanItemsList.size(); i++) { + greaterThanItems[i] = greaterThanItemsList.get(i).getItemName(); + } + session.close(); + return greaterThanItems; + } + + // To get items having price less than 1000 + public String[] lessThanCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.lessThan(rootItem.get("itemPrice"), 1000)); + final List lessThanItemsList = session.createQuery(criteriaItem).getResultList(); + final String lessThanItems[] = new String[lessThanItemsList.size()]; + for (int i = 0; i < lessThanItemsList.size(); i++) { + lessThanItems[i] = lessThanItemsList.get(i).getItemName(); + } + session.close(); + return lessThanItems; + } + + // To get items whose Name start with Chair + public String[] likeCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%chair%")); + final List likeItemsList = session.createQuery(criteriaItem).getResultList(); + final String likeItems[] = new String[likeItemsList.size()]; + for (int i = 0; i < likeItemsList.size(); i++) { + likeItems[i] = likeItemsList.get(i).getItemName(); + } + session.close(); + return likeItems; + } + + // Case sensitive search + public String[] likeCaseCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%Chair%")); + final List ilikeItemsList = session.createQuery(criteriaItem).getResultList(); + final String ilikeItems[] = new String[ilikeItemsList.size()]; + for (int i = 0; i < ilikeItemsList.size(); i++) { + ilikeItems[i] = ilikeItemsList.get(i).getItemName(); + } + session.close(); + return ilikeItems; + } + + // To get records having itemPrice in between 100 and 200 + public String[] betweenCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + // To get items having price more than 1000 + criteriaItem.select(rootItem).where(builder.between(rootItem.get("itemPrice"), 100, 200)); + final List betweenItemsList = session.createQuery(criteriaItem).getResultList(); + final String betweenItems[] = new String[betweenItemsList.size()]; + for (int i = 0; i < betweenItemsList.size(); i++) { + betweenItems[i] = betweenItemsList.get(i).getItemName(); + } + session.close(); + return betweenItems; + } + + // To check if the given property is null + public String[] nullCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription"))); + final List nullItemsList = session.createQuery(criteriaItem).getResultList(); + final String nullDescItems[] = new String[nullItemsList.size()]; + for (int i = 0; i < nullItemsList.size(); i++) { + nullDescItems[i] = nullItemsList.get(i).getItemName(); + } + session.close(); + return nullDescItems; + } + + // To check if the given property is not null + public String[] notNullCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.isNotNull(rootItem.get("itemDescription"))); + final List notNullItemsList = session.createQuery(criteriaItem).getResultList(); + final String notNullDescItems[] = new String[notNullItemsList.size()]; + for (int i = 0; i < notNullItemsList.size(); i++) { + notNullDescItems[i] = notNullItemsList.get(i).getItemName(); + } + session.close(); + return notNullDescItems; + } + + // Adding more than one expression in one cr + public String[] twoCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription"))) + .where(builder.like(rootItem.get("itemName"), "chair%")); + final List notNullItemsList = session.createQuery(criteriaItem).getResultList(); + final String notNullDescItems[] = new String[notNullItemsList.size()]; + for (int i = 0; i < notNullItemsList.size(); i++) { + notNullDescItems[i] = notNullItemsList.get(i).getItemName(); + } + session.close(); + return notNullDescItems; + } + + // To get items matching with the above defined conditions joined + // with Logical AND + public String[] andLogicalCriteria() { + List predicates = new ArrayList(); + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + predicates.add(builder.greaterThan(rootItem.get("itemPrice"), 1000)); + predicates.add(builder.like(rootItem.get("itemName"), "Chair%")); + Predicate andPredicate = builder.and(predicates.toArray(new Predicate[] {})); + criteriaItem.select(rootItem).where(andPredicate); + final List andItemsList = session.createQuery(criteriaItem).getResultList(); + final String andItems[] = new String[andItemsList.size()]; + for (int i = 0; i < andItemsList.size(); i++) { + andItems[i] = andItemsList.get(i).getItemName(); + } + session.close(); + return andItems; + } + + // To get items matching with the above defined conditions joined + // with Logical OR + public String[] orLogicalCriteria() { + List predicates = new ArrayList(); + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + predicates.add(builder.greaterThan(rootItem.get("itemPrice"), 1000)); + predicates.add(builder.like(rootItem.get("itemName"), "Chair%")); + Predicate orPredicate = builder.or(predicates.toArray(new Predicate[] {})); + criteriaItem.select(rootItem).where(orPredicate); + final List orItemsList = session.createQuery(criteriaItem).getResultList(); + final String orItems[] = new String[orItemsList.size()]; + for (int i = 0; i < orItemsList.size(); i++) { + orItems[i] = orItemsList.get(i).getItemName(); + } + session.close(); + return orItems; + } + + // Sorting example + public String[] sortingCriteria() { + List listOrders = new ArrayList(); + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Item.class); + Root rootItem = criteriaItem.from(Item.class); + listOrders.add(builder.asc(rootItem.get("itemName"))); + listOrders.add(builder.desc(rootItem.get("itemPrice"))); + criteriaItem.orderBy(listOrders.toArray(new Order[] {})); + final List sortedItemsList = session.createQuery(criteriaItem).getResultList(); + final String sortedItems[] = new String[sortedItemsList.size()]; + for (int i = 0; i < sortedItemsList.size(); i++) { + sortedItems[i] = sortedItemsList.get(i).getItemName(); + } + session.close(); + return sortedItems; + } + + // Set projections Row Count + public Long[] projectionRowCount() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Tuple.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.multiselect(builder.count(rootItem)); + final List itemProjected = session.createQuery(criteriaItem).getResultList(); + final Long projectedRowCount[] = new Long[1]; + projectedRowCount[0] = (long) itemProjected.get(0).get(0); + session.close(); + return projectedRowCount; + } + + // Set projections average of itemPrice + public Double[] projectionAverage() { + final Session session = HibernateUtil.getHibernateSession(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Tuple.class); + Root rootItem = criteriaItem.from(Item.class); + criteriaItem.multiselect(builder.avg(rootItem.get("itemPrice"))); + final List itemProjected = session.createQuery(criteriaItem).getResultList(); + Double avgItemPrice[] = new Double[1]; + avgItemPrice[0] = Double.valueOf(itemProjected.get(0).get(0).toString()); + session.close(); + return avgItemPrice; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java new file mode 100644 index 0000000000..f4a9b8a678 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java @@ -0,0 +1,58 @@ +package com.baeldung.hibernate.fetching.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.sql.Date; + +@Entity +@Table(name = "USER_ORDER") +public class OrderDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + @Column(name = "ORDER_ID") + private Long orderId; + + public OrderDetail() { + } + + public OrderDetail(Date orderDate, String orderDesc) { + super(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((orderId == null) ? 0 : orderId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OrderDetail other = (OrderDetail) obj; + if (orderId == null) { + if (other.orderId != null) + return false; + } else if (!orderId.equals(other.orderId)) + return false; + + return true; + } + + public Long getOrderId() { + return orderId; + } + + public void setOrderId(Long orderId) { + this.orderId = orderId; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java new file mode 100644 index 0000000000..a1aa746399 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java @@ -0,0 +1,71 @@ +package com.baeldung.hibernate.fetching.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +@Entity +@Table(name = "USER") +public class UserEager implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + @Column(name = "USER_ID") + private Long userId; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") + private Set orderDetail = new HashSet(); + + public UserEager() { + } + + public UserEager(final Long userId) { + super(); + this.userId = userId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final UserEager other = (UserEager) obj; + if (userId == null) { + if (other.userId != null) + return false; + } else if (!userId.equals(other.userId)) + return false; + return true; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(final Long userId) { + this.userId = userId; + } + + public Set getOrderDetail() { + return orderDetail; + } + + public void setOrderDetail(Set orderDetail) { + this.orderDetail = orderDetail; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java new file mode 100644 index 0000000000..e1354b5d24 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java @@ -0,0 +1,71 @@ +package com.baeldung.hibernate.fetching.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +@Entity +@Table(name = "USER") +public class UserLazy implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + @Column(name = "USER_ID") + private Long userId; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") + private Set orderDetail = new HashSet(); + + public UserLazy() { + } + + public UserLazy(final Long userId) { + super(); + this.userId = userId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final UserLazy other = (UserLazy) obj; + if (userId == null) { + if (other.userId != null) + return false; + } else if (!userId.equals(other.userId)) + return false; + return true; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(final Long userId) { + this.userId = userId; + } + + public Set getOrderDetail() { + return orderDetail; + } + + public void setOrderDetail(Set orderDetail) { + this.orderDetail = orderDetail; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java new file mode 100644 index 0000000000..422de2ea93 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java @@ -0,0 +1,28 @@ +package com.baeldung.hibernate.fetching.util; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; + +public class HibernateUtil { + + public static Session getHibernateSession(String fetchMethod) { + // two config files are there + // one with lazy loading enabled + // another lazy = false + SessionFactory sf; + if ("lazy".equals(fetchMethod)) { + sf = new Configuration().configure("fetchingLazy.cfg.xml").buildSessionFactory(); + } else { + sf = new Configuration().configure("fetching.cfg.xml").buildSessionFactory(); + } + + // fetching.cfg.xml is used for this example + return sf.openSession(); + } + + public static Session getHibernateSession() { + return new Configuration().configure("fetching.cfg.xml").buildSessionFactory().openSession(); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java new file mode 100644 index 0000000000..7fc543f693 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java @@ -0,0 +1,68 @@ +package com.baeldung.hibernate.fetching.view; + +import com.baeldung.hibernate.fetching.model.OrderDetail; +import com.baeldung.hibernate.fetching.model.UserEager; +import com.baeldung.hibernate.fetching.model.UserLazy; +import com.baeldung.hibernate.fetching.util.HibernateUtil; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import java.util.List; +import java.util.Set; + +public class FetchingAppView { + + public FetchingAppView() { + + } + + // lazily loaded + public Set lazyLoaded() { + final Session sessionLazy = HibernateUtil.getHibernateSession("lazy"); + List users = sessionLazy.createQuery("From UserLazy").getResultList(); + UserLazy userLazyLoaded = users.get(3); + // since data is lazyloaded so data won't be initialized + return (userLazyLoaded.getOrderDetail()); + } + + // eagerly loaded + public Set eagerLoaded() { + final Session sessionEager = HibernateUtil.getHibernateSession(); + // data should be loaded in the following line + // also note the queries generated + List user = sessionEager.createQuery("From UserEager").getResultList(); + UserEager userEagerLoaded = user.get(3); + return userEagerLoaded.getOrderDetail(); + } + + // creates test data + // call this method to create the data in the database + public void createTestData() { + + final Session session = HibernateUtil.getHibernateSession("lazy"); + Transaction tx = session.beginTransaction(); + final UserLazy user1 = new UserLazy(); + final UserLazy user2 = new UserLazy(); + final UserLazy user3 = new UserLazy(); + + session.save(user1); + session.save(user2); + session.save(user3); + + final OrderDetail order1 = new OrderDetail(); + final OrderDetail order2 = new OrderDetail(); + final OrderDetail order3 = new OrderDetail(); + final OrderDetail order4 = new OrderDetail(); + final OrderDetail order5 = new OrderDetail(); + + session.saveOrUpdate(order1); + session.saveOrUpdate(order2); + session.saveOrUpdate(order3); + session.saveOrUpdate(order4); + session.saveOrUpdate(order5); + + tx.commit(); + session.close(); + + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java new file mode 100644 index 0000000000..182b493592 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarAuditableDao extends IBarDao, IAuditOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java new file mode 100644 index 0000000000..4d7db64240 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.persistence.dao; + +import java.io.Serializable; + +import com.baeldung.persistence.model.Bar; +import org.springframework.data.repository.CrudRepository; + +public interface IBarCrudRepository extends CrudRepository { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java new file mode 100644 index 0000000000..7896a2a84a --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarDao extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java new file mode 100644 index 0000000000..a55a0b0598 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IChildDao extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java new file mode 100644 index 0000000000..ddbb685988 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Foo; + +public interface IFooAuditableDao extends IFooDao, IAuditOperations { + // +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java new file mode 100644 index 0000000000..0935772dbd --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IFooDao extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java new file mode 100644 index 0000000000..03680158bb --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.model.Parent; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IParentDao extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java new file mode 100644 index 0000000000..5a6c76a93a --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import com.google.common.base.Preconditions; + +public abstract class AbstractDao implements IOperations { + + protected Class clazz; + + protected final void setClazz(final Class clazzToSet) { + clazz = Preconditions.checkNotNull(clazzToSet); + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java new file mode 100644 index 0000000000..41184669ad --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java @@ -0,0 +1,37 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.envers.AuditReader; +import org.hibernate.envers.AuditReaderFactory; +import org.hibernate.envers.query.AuditQuery; + +@SuppressWarnings("unchecked") +public class AbstractHibernateAuditableDao extends AbstractHibernateDao implements IAuditOperations { + + @Override + public List getEntitiesAtRevision(final Number revision) { + final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession()); + final AuditQuery query = auditReader.createQuery().forEntitiesAtRevision(clazz, revision); + final List resultList = query.getResultList(); + return resultList; + } + + @Override + public List getEntitiesModifiedAtRevision(final Number revision) { + final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession()); + final AuditQuery query = auditReader.createQuery().forEntitiesModifiedAtRevision(clazz, revision); + final List resultList = query.getResultList(); + return resultList; + } + + @Override + public List getRevisions() { + final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession()); + final AuditQuery query = auditReader.createQuery().forRevisionsOfEntity(clazz, true, true); + final List resultList = query.getResultList(); + return resultList; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java new file mode 100644 index 0000000000..f34866d883 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java @@ -0,0 +1,59 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.base.Preconditions; + +@SuppressWarnings("unchecked") +public abstract class AbstractHibernateDao extends AbstractDao implements IOperations { + + @Autowired + protected SessionFactory sessionFactory; + + // API + + @Override + public T findOne(final long id) { + return (T) getCurrentSession().get(clazz, id); + } + + @Override + public List findAll() { + return getCurrentSession().createQuery("from " + clazz.getName()).getResultList(); + } + + @Override + public void create(final T entity) { + Preconditions.checkNotNull(entity); + getCurrentSession().saveOrUpdate(entity); + } + + @Override + public T update(final T entity) { + Preconditions.checkNotNull(entity); + return (T) getCurrentSession().merge(entity); + } + + @Override + public void delete(final T entity) { + Preconditions.checkNotNull(entity); + getCurrentSession().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + final T entity = findOne(entityId); + Preconditions.checkState(entity != null); + delete(entity); + } + + protected Session getCurrentSession() { + return sessionFactory.getCurrentSession(); + } + +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java new file mode 100644 index 0000000000..69f8e58c25 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java @@ -0,0 +1,56 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +public class AbstractJpaDao extends AbstractDao implements IOperations { + + @PersistenceContext + private EntityManager em; + + // API + + @Override + public T findOne(final long id) { + return em.find(clazz, Long.valueOf(id).intValue()); + } + + @Override + public List findAll() { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(clazz); + final Root rootEntry = cq.from(clazz); + final CriteriaQuery all = cq.select(rootEntry); + final TypedQuery allQuery = em.createQuery(all); + return allQuery.getResultList(); + } + + @Override + public void create(final T entity) { + em.persist(entity); + } + + @Override + public T update(final T entity) { + em.merge(entity); + return entity; + } + + @Override + public void delete(final T entity) { + em.remove(entity); + } + + @Override + public void deleteById(final long entityId) { + delete(findOne(entityId)); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java new file mode 100644 index 0000000000..18b16fa033 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java @@ -0,0 +1,13 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +@Repository +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao { + // +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java new file mode 100644 index 0000000000..169d3fed72 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +public interface IAuditOperations { + + List getEntitiesAtRevision(Number revision); + + List getEntitiesModifiedAtRevision(Number revision); + + List getRevisions(); + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java new file mode 100644 index 0000000000..8d8af18394 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java @@ -0,0 +1,7 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +public interface IGenericDao extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java new file mode 100644 index 0000000000..4ef99221ab --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java @@ -0,0 +1,20 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +public interface IOperations { + + T findOne(final long id); + + List findAll(); + + void create(final T entity); + + T update(final T entity); + + void delete(final T entity); + + void deleteById(final long entityId); + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java new file mode 100644 index 0000000000..e12b6ae2da --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java @@ -0,0 +1,28 @@ +package com.baeldung.persistence.dao.impl; + +import java.util.List; + +import com.baeldung.persistence.dao.IBarAuditableDao; +import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao; +import com.baeldung.persistence.model.Bar; + +public class BarAuditableDao extends AbstractHibernateAuditableDao implements IBarAuditableDao { + + public BarAuditableDao() { + super(); + + setClazz(Bar.class); + } + + // API + + @Override + public List getRevisions() { + final List resultList = super.getRevisions(); + for (final Bar bar : resultList) { + bar.getFooSet().size(); // force FooSet initialization + } + return resultList; + } + +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java new file mode 100644 index 0000000000..0ead802dc5 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.model.Bar; +import org.springframework.stereotype.Repository; + +@Repository +public class BarDao extends AbstractHibernateDao implements IBarDao { + + public BarDao() { + super(); + + setClazz(Bar.class); + } + + // API + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java new file mode 100644 index 0000000000..e0fa382d41 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.AbstractJpaDao; +import com.baeldung.persistence.model.Bar; +import org.springframework.stereotype.Repository; + +@Repository +public class BarJpaDao extends AbstractJpaDao implements IBarDao { + + public BarJpaDao() { + super(); + + setClazz(Bar.class); + } + + // API + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java new file mode 100644 index 0000000000..b55da6e43a --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.dao.IChildDao; +import org.springframework.stereotype.Repository; + +@Repository +public class ChildDao extends AbstractHibernateDao implements IChildDao { + + public ChildDao() { + super(); + + setClazz(Child.class); + } + + // API + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java new file mode 100644 index 0000000000..05064c1478 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java @@ -0,0 +1,17 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.dao.IFooAuditableDao; + +public class FooAuditableDao extends AbstractHibernateAuditableDao implements IFooAuditableDao { + + public FooAuditableDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java new file mode 100644 index 0000000000..787c449b1d --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.model.Foo; +import org.springframework.stereotype.Repository; + +@Repository +public class FooDao extends AbstractHibernateDao implements IFooDao { + + public FooDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java new file mode 100644 index 0000000000..4602b5f30e --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.IParentDao; +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.model.Parent; +import org.springframework.stereotype.Repository; + +@Repository +public class ParentDao extends AbstractHibernateDao implements IParentDao { + + public ParentDao() { + super(); + + setClazz(Parent.class); + } + + // API + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java new file mode 100644 index 0000000000..c7f05254cc --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java @@ -0,0 +1,242 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; +import java.util.Date; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +import org.hibernate.annotations.OrderBy; +import org.hibernate.envers.Audited; +import org.jboss.logging.Logger; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import com.google.common.collect.Sets; + +@Entity +@NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b") +@Audited +@EntityListeners(AuditingEntityListener.class) +public class Bar implements Serializable { + + private static Logger logger = Logger.getLogger(Bar.class); + + public enum OPERATION { + INSERT, UPDATE, DELETE; + private String value; + + OPERATION() { + value = toString(); + } + + public String getValue() { + return value; + } + + public static OPERATION parse(final String value) { + OPERATION operation = null; + for (final OPERATION op : OPERATION.values()) { + if (op.getValue().equals(value)) { + operation = op; + break; + } + } + return operation; + } + }; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private int id; + + @Column(name = "name") + private String name; + + @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @OrderBy(clause = "NAME DESC") + // @NotAudited + private Set fooSet = Sets.newHashSet(); + + @Column(name = "operation") + private String operation; + + @Column(name = "timestamp") + private long timestamp; + + @Column(name = "created_date", updatable = false, nullable = false) + @CreatedDate + private long createdDate; + + @Column(name = "modified_date") + @LastModifiedDate + private long modifiedDate; + + @Column(name = "created_by") + @CreatedBy + private String createdBy; + + @Column(name = "modified_by") + @LastModifiedBy + private String modifiedBy; + + public Bar() { + super(); + } + + public Bar(final String name) { + super(); + + this.name = name; + } + + // API + + public Set getFooSet() { + return fooSet; + } + + public void setFooSet(final Set fooSet) { + this.fooSet = fooSet; + } + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public OPERATION getOperation() { + return OPERATION.parse(operation); + } + + public void setOperation(final OPERATION operation) { + this.operation = operation.getValue(); + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(final long timestamp) { + this.timestamp = timestamp; + } + + public long getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(final long createdDate) { + this.createdDate = createdDate; + } + + public long getModifiedDate() { + return modifiedDate; + } + + public void setModifiedDate(final long modifiedDate) { + this.modifiedDate = modifiedDate; + } + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(final String createdBy) { + this.createdBy = createdBy; + } + + public String getModifiedBy() { + return modifiedBy; + } + + public void setModifiedBy(final String modifiedBy) { + this.modifiedBy = modifiedBy; + } + + public void setOperation(final String operation) { + this.operation = operation; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Bar other = (Bar) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Bar [name=").append(name).append("]"); + return builder.toString(); + } + + @PrePersist + public void onPrePersist() { + logger.info("@PrePersist"); + audit(OPERATION.INSERT); + } + + @PreUpdate + public void onPreUpdate() { + logger.info("@PreUpdate"); + audit(OPERATION.UPDATE); + } + + @PreRemove + public void onPreRemove() { + logger.info("@PreRemove"); + audit(OPERATION.DELETE); + } + + private void audit(final OPERATION operation) { + setOperation(operation); + setTimestamp((new Date()).getTime()); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java new file mode 100644 index 0000000000..19cfb2e237 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java @@ -0,0 +1,51 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToOne; + +@Entity +public class Child implements Serializable { + + @Id + @GeneratedValue + private long id; + + @OneToOne(mappedBy = "child") + private Parent parent; + + public Child() { + super(); + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public Parent getParent() { + return parent; + } + + public void setParent(final Parent parent) { + this.parent = parent; + } + + // + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Child [id=").append(id).append("]"); + return builder.toString(); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java new file mode 100644 index 0000000000..d36a1e58cf --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java @@ -0,0 +1,105 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedNativeQueries; +import javax.persistence.NamedNativeQuery; + +import org.hibernate.envers.Audited; + +@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) }) +@Entity +@Audited +// @Proxy(lazy = false) +public class Foo implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private long id; + + @Column(name = "name") + private String name; + + @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "BAR_ID") + private Bar bar = new Bar(); + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + this.name = name; + } + + // + + public Bar getBar() { + return bar; + } + + public void setBar(final Bar bar) { + this.bar = bar; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java new file mode 100644 index 0000000000..fa6948990b --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java @@ -0,0 +1,60 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Entity +public class Parent implements Serializable { + + @Id + @GeneratedValue + private long id; + + @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH }) + @JoinColumn(name = "child_fk") + private Child child; + + public Parent() { + super(); + } + + public Parent(final Child child) { + super(); + + this.child = child; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public Child getChild() { + return child; + } + + public void setChild(final Child child) { + this.child = child; + } + + // + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Parent [id=").append(id).append("]"); + return builder.toString(); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java new file mode 100644 index 0000000000..6a95a7acf5 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java @@ -0,0 +1,31 @@ +package com.baeldung.persistence.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue + private Long id; + + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java new file mode 100644 index 0000000000..33e5634d12 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarAuditableService extends IBarService, IAuditOperations { + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java new file mode 100644 index 0000000000..21185b5990 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarService extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java new file mode 100644 index 0000000000..afe67a70c2 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IChildService extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java new file mode 100644 index 0000000000..b787e7fe91 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Foo; + +public interface IFooAuditableService extends IFooService, IAuditOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java new file mode 100644 index 0000000000..ffdb53964a --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IFooService extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java new file mode 100644 index 0000000000..f941416aac --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Parent; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IParentService extends IOperations { + // +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java new file mode 100644 index 0000000000..8e2df15519 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java @@ -0,0 +1,31 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(value = "hibernateTransactionManager") +public abstract class AbstractHibernateAuditableService extends AbstractHibernateService + implements IOperations, IAuditOperations { + + @Override + public List getEntitiesAtRevision(final Number revision) { + return getAuditableDao().getEntitiesAtRevision(revision); + } + + @Override + public List getEntitiesModifiedAtRevision(final Number revision) { + return getAuditableDao().getEntitiesModifiedAtRevision(revision); + } + + @Override + public List getRevisions() { + return getAuditableDao().getRevisions(); + } + + abstract protected IAuditOperations getAuditableDao(); + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java new file mode 100644 index 0000000000..5da2f299f1 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java @@ -0,0 +1,43 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(value = "hibernateTransactionManager") +public abstract class AbstractHibernateService extends AbstractService implements + IOperations { + + @Override + public T findOne(final long id) { + return super.findOne(id); + } + + @Override + public List findAll() { + return super.findAll(); + } + + @Override + public void create(final T entity) { + super.create(entity); + } + + @Override + public T update(final T entity) { + return super.update(entity); + } + + @Override + public void delete(final T entity) { + super.delete(entity); + } + + @Override + public void deleteById(final long entityId) { + super.deleteById(entityId); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java new file mode 100644 index 0000000000..a1c6fe9edf --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java @@ -0,0 +1,42 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(value = "jpaTransactionManager") +public abstract class AbstractJpaService extends AbstractService implements IOperations { + + @Override + public T findOne(final long id) { + return super.findOne(id); + } + + @Override + public List findAll() { + return super.findAll(); + } + + @Override + public void create(final T entity) { + super.create(entity); + } + + @Override + public T update(final T entity) { + return super.update(entity); + } + + @Override + public void delete(final T entity) { + super.delete(entity); + } + + @Override + public void deleteById(final long entityId) { + super.deleteById(entityId); + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java new file mode 100644 index 0000000000..9b001b1fac --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java @@ -0,0 +1,42 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; + +public abstract class AbstractService implements IOperations { + + @Override + public T findOne(final long id) { + return getDao().findOne(id); + } + + @Override + public List findAll() { + return getDao().findAll(); + } + + @Override + public void create(final T entity) { + getDao().create(entity); + } + + @Override + public T update(final T entity) { + return getDao().update(entity); + } + + @Override + public void delete(final T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + getDao().deleteById(entityId); + } + + protected abstract IOperations getDao(); + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java new file mode 100644 index 0000000000..cef483e6bf --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java @@ -0,0 +1,46 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.data.repository.CrudRepository; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; + +@Transactional(value = "jpaTransactionManager") +public abstract class AbstractSpringDataJpaService implements IOperations { + + @Override + public T findOne(final long id) { + return getDao().findOne(Long.valueOf(id)); + } + + @Override + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } + + @Override + public void create(final T entity) { + getDao().save(entity); + } + + @Override + public T update(final T entity) { + return getDao().save(entity); + } + + @Override + public void delete(final T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + getDao().delete(Long.valueOf(entityId)); + } + + protected abstract CrudRepository getDao(); +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java new file mode 100644 index 0000000000..d84c28caa5 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java @@ -0,0 +1,41 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.service.common.AbstractHibernateAuditableService; +import com.baeldung.persistence.dao.IBarAuditableDao; +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarAuditableService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class BarAuditableService extends AbstractHibernateAuditableService implements IBarAuditableService { + + @Autowired + @Qualifier("barHibernateDao") + private IBarDao dao; + + @Autowired + @Qualifier("barHibernateAuditableDao") + private IBarAuditableDao auditDao; + + public BarAuditableService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + + @Override + protected IAuditOperations getAuditableDao() { + return auditDao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java new file mode 100644 index 0000000000..1c1b7a2274 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.persistence.service.common.AbstractJpaService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class BarJpaService extends AbstractJpaService implements IBarService { + + @Autowired + @Qualifier("barJpaDao") + private IBarDao dao; + + public BarJpaService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java new file mode 100644 index 0000000000..32d1f919c5 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class BarService extends AbstractHibernateService implements IBarService { + + @Autowired + @Qualifier("barHibernateDao") + private IBarDao dao; + + public BarService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java new file mode 100644 index 0000000000..4a55d08a35 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java @@ -0,0 +1,26 @@ +package com.baeldung.persistence.service.impl; + +import java.io.Serializable; + +import com.baeldung.persistence.service.common.AbstractSpringDataJpaService; +import com.baeldung.persistence.dao.IBarCrudRepository; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.CrudRepository; + +public class BarSpringDataJpaService extends AbstractSpringDataJpaService implements IBarService { + + @Autowired + private IBarCrudRepository dao; + + public BarSpringDataJpaService() { + super(); + } + + @Override + protected CrudRepository getDao() { + return dao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java new file mode 100644 index 0000000000..417fe2c49a --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java @@ -0,0 +1,28 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.service.IChildService; +import com.baeldung.persistence.dao.IChildDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ChildService extends AbstractHibernateService implements IChildService { + + @Autowired + private IChildDao dao; + + public ChildService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java new file mode 100644 index 0000000000..45ad315c42 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java @@ -0,0 +1,41 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.persistence.service.common.AbstractHibernateAuditableService; +import com.baeldung.persistence.dao.IFooAuditableDao; +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class FooAuditableService extends AbstractHibernateAuditableService implements IFooAuditableService { + + @Autowired + @Qualifier("fooHibernateDao") + private IFooDao dao; + + @Autowired + @Qualifier("fooHibernateAuditableDao") + private IFooAuditableDao auditDao; + + public FooAuditableService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + + @Override + protected IAuditOperations getAuditableDao() { + return auditDao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java new file mode 100644 index 0000000000..84cf018fee --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class FooService extends AbstractHibernateService implements IFooService { + + @Autowired + @Qualifier("fooHibernateDao") + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java new file mode 100644 index 0000000000..078acfc369 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java @@ -0,0 +1,28 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.model.Parent; +import com.baeldung.persistence.service.IParentService; +import com.baeldung.persistence.dao.IParentDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ParentService extends AbstractHibernateService implements IParentService { + + @Autowired + private IParentDao dao; + + public ParentService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java new file mode 100644 index 0000000000..67ab97e516 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -0,0 +1,173 @@ +package com.baeldung.spring; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.baeldung.persistence.dao.IBarAuditableDao; +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.IFooAuditableDao; +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.dao.impl.BarAuditableDao; +import com.baeldung.persistence.dao.impl.BarDao; +import com.baeldung.persistence.dao.impl.BarJpaDao; +import com.baeldung.persistence.dao.impl.FooAuditableDao; +import com.baeldung.persistence.dao.impl.FooDao; +import com.baeldung.persistence.service.IBarAuditableService; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.persistence.service.impl.BarAuditableService; +import com.baeldung.persistence.service.impl.BarJpaService; +import com.baeldung.persistence.service.impl.BarSpringDataJpaService; +import com.baeldung.persistence.service.impl.FooAuditableService; +import com.baeldung.persistence.service.impl.FooService; +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") +@EnableJpaAuditing +@PropertySource({ "classpath:persistence-mysql.properties" }) +@ComponentScan({ "com.baeldung.persistence" }) +public class PersistenceConfig { + + @Autowired + private Environment env; + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); + emf.setDataSource(restDataSource()); + emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + + final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + emf.setJpaVendorAdapter(vendorAdapter); + emf.setJpaProperties(hibernateProperties()); + + return emf; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + @Bean + public PlatformTransactionManager jpaTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + @Bean + public IBarService barJpaService() { + return new BarJpaService(); + } + + @Bean + public IBarService barSpringDataJpaService() { + return new BarSpringDataJpaService(); + } + + @Bean + public IFooService fooHibernateService() { + return new FooService(); + } + + @Bean + public IBarAuditableService barHibernateAuditableService() { + return new BarAuditableService(); + } + + @Bean + public IFooAuditableService fooHibernateAuditableService() { + return new FooAuditableService(); + } + + @Bean + public IBarDao barJpaDao() { + return new BarJpaDao(); + } + + @Bean + public IBarDao barHibernateDao() { + return new BarDao(); + } + + @Bean + public IBarAuditableDao barHibernateAuditableDao() { + return new BarAuditableDao(); + } + + @Bean + public IFooDao fooHibernateDao() { + return new FooDao(); + } + + @Bean + public IFooAuditableDao fooHibernateAuditableDao() { + return new FooAuditableDao(); + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + hibernateProperties.setProperty("hibernate.show_sql", "true"); + + // Envers properties + hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); + + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java new file mode 100644 index 0000000000..e93fcca3e1 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java @@ -0,0 +1,14 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@ComponentScan({ "com.baeldung.persistence.dao", "com.baeldung.persistence.service" }) +@ImportResource({ "classpath:hibernate5Config.xml" }) +public class PersistenceXmlConfig { + +} \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/criteria.cfg.xml b/spring-hibernate5/src/main/resources/criteria.cfg.xml new file mode 100644 index 0000000000..0b865fc4d1 --- /dev/null +++ b/spring-hibernate5/src/main/resources/criteria.cfg.xml @@ -0,0 +1,17 @@ + + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + root + org.hibernate.dialect.MySQLDialect + true + + + \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/criteria_create_queries.sql b/spring-hibernate5/src/main/resources/criteria_create_queries.sql new file mode 100644 index 0000000000..3a627dd38c --- /dev/null +++ b/spring-hibernate5/src/main/resources/criteria_create_queries.sql @@ -0,0 +1,7 @@ +CREATE TABLE `item` ( + `ITEM_ID` int(11) NOT NULL AUTO_INCREMENT, + `ITEM_DESC` varchar(100) DEFAULT NULL, + `ITEM_PRICE` int(11) NOT NULL, + `ITEM_NAME` varchar(255) NOT NULL, + PRIMARY KEY (`ITEM_ID`) +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1; diff --git a/spring-hibernate5/src/main/resources/fetching.cfg.xml b/spring-hibernate5/src/main/resources/fetching.cfg.xml new file mode 100644 index 0000000000..b1ffecafce --- /dev/null +++ b/spring-hibernate5/src/main/resources/fetching.cfg.xml @@ -0,0 +1,20 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + root + org.hibernate.dialect.MySQLDialect + true + validate + + + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml b/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml new file mode 100644 index 0000000000..a18fdbfa99 --- /dev/null +++ b/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml @@ -0,0 +1,17 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + root + org.hibernate.dialect.MySQLDialect + true + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/fetching_create_queries.sql b/spring-hibernate5/src/main/resources/fetching_create_queries.sql new file mode 100644 index 0000000000..b36d9828f1 --- /dev/null +++ b/spring-hibernate5/src/main/resources/fetching_create_queries.sql @@ -0,0 +1,14 @@ +CREATE TABLE `user` ( + `user_id` int(10) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`user_id`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 ; + + +CREATE TABLE `user_order` ( + `ORDER_ID` int(10) NOT NULL AUTO_INCREMENT, + `USER_ID` int(10) NOT NULL DEFAULT '0', + PRIMARY KEY (`ORDER_ID`,`USER_ID`), + KEY `USER_ID` (`USER_ID`), + CONSTRAINT `user_order_ibfk_1` FOREIGN KEY (`USER_ID`) REFERENCES `USER` (`user_id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1; + diff --git a/spring-hibernate5/src/main/resources/hibernate5Config.xml b/spring-hibernate5/src/main/resources/hibernate5Config.xml new file mode 100644 index 0000000000..55546a862a --- /dev/null +++ b/spring-hibernate5/src/main/resources/hibernate5Config.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/insert_statements.sql b/spring-hibernate5/src/main/resources/insert_statements.sql new file mode 100644 index 0000000000..ae008f29bc --- /dev/null +++ b/spring-hibernate5/src/main/resources/insert_statements.sql @@ -0,0 +1,31 @@ +insert into item (item_id, item_name, item_desc, item_price) +values(1,'item One', 'test 1', 35.12); + +insert into item (item_id, item_name, item_desc, item_price) +values(2,'Pogo stick', 'Pogo stick', 466.12); +insert into item (item_id, item_name, item_desc, item_price) +values(3,'Raft', 'Raft', 345.12); + +insert into item (item_id, item_name, item_desc, item_price) +values(4,'Skate Board', 'Skating', 135.71); + +insert into item (item_id, item_name, item_desc, item_price) +values(5,'Umbrella', 'Umbrella for Rain', 619.25); + +insert into item (item_id, item_name, item_desc, item_price) +values(6,'Glue', 'Glue for home', 432.73); + +insert into item (item_id, item_name, item_desc, item_price) +values(7,'Paint', 'Paint for Room', 1311.40); + +insert into item (item_id, item_name, item_desc, item_price) +values(8,'Red paint', 'Red paint for room', 1135.71); + +insert into item (item_id, item_name, item_desc, item_price) +values(9,'Household Chairs', 'Chairs for house', 25.71); + +insert into item (item_id, item_name, item_desc, item_price) +values(10,'Office Chairs', 'Chairs for office', 395.98); + +insert into item (item_id, item_name, item_desc, item_price) +values(11,'Outdoor Chairs', 'Chairs for outdoor activities', 1234.36); diff --git a/spring-hibernate5/src/main/resources/logback.xml b/spring-hibernate5/src/main/resources/logback.xml new file mode 100644 index 0000000000..71a6d50a58 --- /dev/null +++ b/spring-hibernate5/src/main/resources/logback.xml @@ -0,0 +1,22 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/persistence-mysql.properties b/spring-hibernate5/src/main/resources/persistence-mysql.properties new file mode 100644 index 0000000000..1180929b30 --- /dev/null +++ b/spring-hibernate5/src/main/resources/persistence-mysql.properties @@ -0,0 +1,13 @@ +# jdbc.X +jdbc.driverClassName=com.mysql.cj.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true +jdbc.user=tutorialuser +jdbc.pass=tutorialmy5ql + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop + +# envers.X +envers.audit_table_suffix=_audit_log diff --git a/spring-hibernate5/src/main/resources/stored_procedure.sql b/spring-hibernate5/src/main/resources/stored_procedure.sql new file mode 100644 index 0000000000..9cedb75c37 --- /dev/null +++ b/spring-hibernate5/src/main/resources/stored_procedure.sql @@ -0,0 +1,20 @@ +DELIMITER // + CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255)) + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo WHERE name = fooName; + END // +DELIMITER ; + + +DELIMITER // + CREATE PROCEDURE GetAllFoos() + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo; + END // +DELIMITER ; \ No newline at end of file diff --git a/spring-hibernate5/src/main/resources/webSecurityConfig.xml b/spring-hibernate5/src/main/resources/webSecurityConfig.xml new file mode 100644 index 0000000000..e5c19a4ad7 --- /dev/null +++ b/spring-hibernate5/src/main/resources/webSecurityConfig.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java new file mode 100644 index 0000000000..7caa02f156 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java @@ -0,0 +1,194 @@ +package com.baeldung.hibernate.criteria; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.hibernate.Session; +import org.junit.Test; + +import com.baeldung.hibernate.criteria.model.Item; +import com.baeldung.hibernate.criteria.util.HibernateUtil; +import com.baeldung.hibernate.criteria.view.ApplicationView; + +public class HibernateCriteriaIntegrationTest { + + final private ApplicationView av = new ApplicationView(); + + @Test + public void testPerformanceOfCriteria() { + assertTrue(av.checkIfCriteriaTimeLower()); + } + + @Test + public void testLikeCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedLikeList = session.createQuery("From Item where itemName like '%chair%'") + .getResultList(); + final String expectedLikeItems[] = new String[expectedLikeList.size()]; + for (int i = 0; i < expectedLikeList.size(); i++) { + expectedLikeItems[i] = expectedLikeList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedLikeItems, av.likeCriteria()); + } + + @Test + public void testILikeCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedChairCaseList = session.createQuery("From Item where itemName like '%Chair%'") + .getResultList(); + final String expectedChairCaseItems[] = new String[expectedChairCaseList.size()]; + for (int i = 0; i < expectedChairCaseList.size(); i++) { + expectedChairCaseItems[i] = expectedChairCaseList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedChairCaseItems, av.likeCaseCriteria()); + + } + + @Test + public void testNullCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedIsNullDescItemsList = session.createQuery("From Item where itemDescription is null") + .getResultList(); + final String expectedIsNullDescItems[] = new String[expectedIsNullDescItemsList.size()]; + for (int i = 0; i < expectedIsNullDescItemsList.size(); i++) { + expectedIsNullDescItems[i] = expectedIsNullDescItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedIsNullDescItems, av.nullCriteria()); + } + + @Test + public void testIsNotNullCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedIsNotNullDescItemsList = session.createQuery( + "From Item where itemDescription is not null").getResultList(); + final String expectedIsNotNullDescItems[] = new String[expectedIsNotNullDescItemsList.size()]; + for (int i = 0; i < expectedIsNotNullDescItemsList.size(); i++) { + expectedIsNotNullDescItems[i] = expectedIsNotNullDescItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedIsNotNullDescItems, av.notNullCriteria()); + + } + + @Test + public void testAverageProjection() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedAvgProjItemsList = session.createQuery("Select avg(itemPrice) from Item item") + .getResultList(); + + final Double expectedAvgProjItems[] = new Double[expectedAvgProjItemsList.size()]; + for (int i = 0; i < expectedAvgProjItemsList.size(); i++) { + expectedAvgProjItems[i] = expectedAvgProjItemsList.get(i); + } + session.close(); + assertArrayEquals(expectedAvgProjItems, av.projectionAverage()); + + } + + @Test + public void testRowCountProjection() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedCountProjItemsList = session.createQuery("Select count(*) from Item").getResultList(); + final Long expectedCountProjItems[] = new Long[expectedCountProjItemsList.size()]; + for (int i = 0; i < expectedCountProjItemsList.size(); i++) { + expectedCountProjItems[i] = expectedCountProjItemsList.get(i); + } + session.close(); + assertArrayEquals(expectedCountProjItems, av.projectionRowCount()); + } + + @Test + public void testOrCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedOrCritItemsList = session.createQuery( + "From Item where itemPrice>1000 or itemName like 'Chair%'").getResultList(); + final String expectedOrCritItems[] = new String[expectedOrCritItemsList.size()]; + for (int i = 0; i < expectedOrCritItemsList.size(); i++) { + expectedOrCritItems[i] = expectedOrCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedOrCritItems, av.orLogicalCriteria()); + } + + @Test + public void testAndCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedAndCritItemsList = session.createQuery( + "From Item where itemPrice>1000 and itemName like 'Chair%'").getResultList(); + final String expectedAndCritItems[] = new String[expectedAndCritItemsList.size()]; + for (int i = 0; i < expectedAndCritItemsList.size(); i++) { + expectedAndCritItems[i] = expectedAndCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedAndCritItems, av.andLogicalCriteria()); + } + + @Test + public void testMultiCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedMultiCritItemsList = session.createQuery( + "From Item where itemDescription is null and itemName like'chair%'").getResultList(); + final String expectedMultiCritItems[] = new String[expectedMultiCritItemsList.size()]; + for (int i = 0; i < expectedMultiCritItemsList.size(); i++) { + expectedMultiCritItems[i] = expectedMultiCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedMultiCritItems, av.twoCriteria()); + } + + @Test + public void testSortCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedSortCritItemsList = session.createQuery( + "From Item order by itemName asc, itemPrice desc").getResultList(); + final String expectedSortCritItems[] = new String[expectedSortCritItemsList.size()]; + for (int i = 0; i < expectedSortCritItemsList.size(); i++) { + expectedSortCritItems[i] = expectedSortCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedSortCritItems, av.sortingCriteria()); + } + + @Test + public void testGreaterThanCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedGreaterThanList = session.createQuery("From Item where itemPrice>1000") + .getResultList(); + final String expectedGreaterThanItems[] = new String[expectedGreaterThanList.size()]; + for (int i = 0; i < expectedGreaterThanList.size(); i++) { + expectedGreaterThanItems[i] = expectedGreaterThanList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedGreaterThanItems, av.greaterThanCriteria()); + } + + @Test + public void testLessThanCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedLessList = session.createQuery("From Item where itemPrice<1000").getResultList(); + final String expectedLessThanItems[] = new String[expectedLessList.size()]; + for (int i = 0; i < expectedLessList.size(); i++) { + expectedLessThanItems[i] = expectedLessList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedLessThanItems, av.lessThanCriteria()); + } + + @Test + public void betweenCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedBetweenList = session.createQuery("From Item where itemPrice between 100 and 200") + .getResultList(); + final String expectedPriceBetweenItems[] = new String[expectedBetweenList.size()]; + for (int i = 0; i < expectedBetweenList.size(); i++) { + expectedPriceBetweenItems[i] = expectedBetweenList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria()); + } +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java new file mode 100644 index 0000000000..99164efb7a --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java @@ -0,0 +1,15 @@ +package com.baeldung.hibernate.criteria; + +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +public class HibernateCriteriaTestRunner { + + public static void main(final String[] args) { + Result result = JUnitCore.runClasses(HibernateCriteriaTestSuite.class); + for (Failure failure : result.getFailures()) { + + } + } +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java new file mode 100644 index 0000000000..dc1040734f --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java @@ -0,0 +1,11 @@ +package com.baeldung.hibernate.criteria; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ HibernateCriteriaIntegrationTest.class }) + +public class HibernateCriteriaTestSuite { + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java new file mode 100644 index 0000000000..65bf36f8bf --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java @@ -0,0 +1,42 @@ +package com.baeldung.hibernate.fetching; + +import com.baeldung.hibernate.fetching.model.OrderDetail; +import com.baeldung.hibernate.fetching.view.FetchingAppView; +import org.hibernate.Hibernate; +import org.junit.Before; +import org.junit.Test; + +import java.util.Set; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class HibernateFetchingIntegrationTest { + + // this loads sample data in the database + @Before + public void addFecthingTestData() { + FetchingAppView fav = new FetchingAppView(); + fav.createTestData(); + } + + // testLazyFetching() tests the lazy loading + // Since it lazily loaded so orderDetalSetLazy won't + // be initialized + @Test + public void testLazyFetching() { + FetchingAppView fav = new FetchingAppView(); + Set orderDetalSetLazy = fav.lazyLoaded(); + assertFalse(Hibernate.isInitialized(orderDetalSetLazy)); + } + + // testEagerFetching() tests the eager loading + // Since it eagerly loaded so orderDetalSetLazy would + // be initialized + @Test + public void testEagerFetching() { + FetchingAppView fav = new FetchingAppView(); + Set orderDetalSetEager = fav.eagerLoaded(); + assertTrue(Hibernate.isInitialized(orderDetalSetEager)); + } +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java new file mode 100644 index 0000000000..f5c45a5d6f --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java @@ -0,0 +1,25 @@ +package com.baeldung.persistence; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import com.baeldung.persistence.audit.AuditTestSuite; +import com.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest; +import com.baeldung.persistence.hibernate.FooSortingPersistenceIntegrationTest; +import com.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest; +import com.baeldung.persistence.service.FooServicePersistenceIntegrationTest; +import com.baeldung.persistence.service.ParentServicePersistenceIntegrationTest; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ // @formatter:off + AuditTestSuite.class + ,FooServiceBasicPersistenceIntegrationTest.class + ,FooPaginationPersistenceIntegrationTest.class + ,FooServicePersistenceIntegrationTest.class + ,ParentServicePersistenceIntegrationTest.class + ,FooSortingPersistenceIntegrationTest.class + +}) // @formatter:on +public class IntegrationTestSuite { + // +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java new file mode 100644 index 0000000000..34c725d62b --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.audit; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ // @formatter:off + EnversFooBarAuditIntegrationTest.class, + JPABarAuditIntegrationTest.class, + SpringDataJPABarAuditIntegrationTest.class +}) // @formatter:on +public class AuditTestSuite { + // +} \ No newline at end of file diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java new file mode 100644 index 0000000000..ed2e111c8f --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java @@ -0,0 +1,142 @@ +package com.baeldung.persistence.audit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IBarAuditableService; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Bar; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class EnversFooBarAuditIntegrationTest { + + private static Logger logger = LoggerFactory.getLogger(EnversFooBarAuditIntegrationTest.class); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("setUpBeforeClass()"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("tearDownAfterClass()"); + } + + @Autowired + @Qualifier("fooHibernateAuditableService") + private IFooAuditableService fooService; + + @Autowired + @Qualifier("barHibernateAuditableService") + private IBarAuditableService barService; + + @Autowired + private SessionFactory sessionFactory; + + private Session session; + + @Before + public void setUp() throws Exception { + logger.info("setUp()"); + makeRevisions(); + session = sessionFactory.openSession(); + } + + @After + public void tearDown() throws Exception { + logger.info("tearDown()"); + session.close(); + } + + private void makeRevisions() { + final Bar bar = rev1(); + rev2(bar); + rev3(bar); + rev4(bar); + } + + // REV #1: insert BAR & FOO1 + private Bar rev1() { + final Bar bar = new Bar("BAR"); + final Foo foo1 = new Foo("FOO1"); + foo1.setBar(bar); + fooService.create(foo1); + return bar; + } + + // REV #2: insert FOO2 & update BAR + private void rev2(final Bar bar) { + final Foo foo2 = new Foo("FOO2"); + foo2.setBar(bar); + fooService.create(foo2); + } + + // REV #3: update BAR + private void rev3(final Bar bar) { + + bar.setName("BAR1"); + barService.update(bar); + } + + // REV #4: insert FOO3 & update BAR + private void rev4(final Bar bar) { + + final Foo foo3 = new Foo("FOO3"); + foo3.setBar(bar); + fooService.create(foo3); + } + + @Test + public final void whenFooBarsModified_thenFooBarsAudited() { + + List barRevisionList; + List fooRevisionList; + + // test Bar revisions + + barRevisionList = barService.getRevisions(); + + assertNotNull(barRevisionList); + assertEquals(4, barRevisionList.size()); + + assertEquals("BAR", barRevisionList.get(0).getName()); + assertEquals("BAR", barRevisionList.get(1).getName()); + assertEquals("BAR1", barRevisionList.get(2).getName()); + assertEquals("BAR1", barRevisionList.get(3).getName()); + + assertEquals(1, barRevisionList.get(0).getFooSet().size()); + assertEquals(2, barRevisionList.get(1).getFooSet().size()); + assertEquals(2, barRevisionList.get(2).getFooSet().size()); + assertEquals(3, barRevisionList.get(3).getFooSet().size()); + + // test Foo revisions + + fooRevisionList = fooService.getRevisions(); + assertNotNull(fooRevisionList); + assertEquals(3, fooRevisionList.size()); + assertEquals("FOO1", fooRevisionList.get(0).getName()); + assertEquals("FOO2", fooRevisionList.get(1).getName()); + assertEquals("FOO3", fooRevisionList.get(2).getName()); + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java new file mode 100644 index 0000000000..b63a4b989b --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java @@ -0,0 +1,102 @@ +package com.baeldung.persistence.audit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; + +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Bar.OPERATION; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.spring.PersistenceConfig; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class JPABarAuditIntegrationTest { + + private static Logger logger = LoggerFactory.getLogger(JPABarAuditIntegrationTest.class); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("setUpBeforeClass()"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("tearDownAfterClass()"); + } + + @Autowired + @Qualifier("barJpaService") + private IBarService barService; + + @Autowired + private EntityManagerFactory entityManagerFactory; + + private EntityManager em; + + @Before + public void setUp() throws Exception { + logger.info("setUp()"); + em = entityManagerFactory.createEntityManager(); + } + + @After + public void tearDown() throws Exception { + logger.info("tearDown()"); + em.close(); + } + + @Test + public final void whenBarsModified_thenBarsAudited() { + + // insert BAR1 + Bar bar1 = new Bar("BAR1"); + barService.create(bar1); + + // update BAR1 + bar1.setName("BAR1a"); + barService.update(bar1); + + // insert BAR2 + Bar bar2 = new Bar("BAR2"); + barService.create(bar2); + + // update BAR1 + bar1.setName("BAR1b"); + barService.update(bar1); + + // get BAR1 and BAR2 from the DB and check the audit values + // detach instances from persistence context to make sure we fire db + em.detach(bar1); + em.detach(bar2); + bar1 = barService.findOne(bar1.getId()); + bar2 = barService.findOne(bar2.getId()); + + assertNotNull(bar1); + assertNotNull(bar2); + assertEquals(OPERATION.UPDATE, bar1.getOperation()); + assertEquals(OPERATION.INSERT, bar2.getOperation()); + assertTrue(bar1.getTimestamp() > bar2.getTimestamp()); + + barService.deleteById(bar1.getId()); + barService.deleteById(bar2.getId()); + + } + +} \ No newline at end of file diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java new file mode 100644 index 0000000000..e794b282f6 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java @@ -0,0 +1,76 @@ +package com.baeldung.persistence.audit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; + +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.spring.PersistenceConfig; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringDataJPABarAuditIntegrationTest { + + private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditIntegrationTest.class); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("setUpBeforeClass()"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("tearDownAfterClass()"); + } + + @Autowired + @Qualifier("barSpringDataJpaService") + private IBarService barService; + + @Autowired + private EntityManagerFactory entityManagerFactory; + + private EntityManager em; + + @Before + public void setUp() throws Exception { + logger.info("setUp()"); + em = entityManagerFactory.createEntityManager(); + } + + @After + public void tearDown() throws Exception { + logger.info("tearDown()"); + em.close(); + } + + @Test + @WithMockUser(username = "tutorialuser") + public final void whenBarsModified_thenBarsAudited() { + Bar bar = new Bar("BAR1"); + barService.create(bar); + assertEquals(bar.getCreatedDate(), bar.getModifiedDate()); + assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy()); + bar.setName("BAR2"); + bar = barService.update(bar); + assertTrue(bar.getCreatedDate() < bar.getModifiedDate()); + assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy()); + } +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java new file mode 100644 index 0000000000..da840dc027 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java @@ -0,0 +1,101 @@ +package com.baeldung.persistence.hibernate; + +import java.util.List; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Bar; +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import com.google.common.collect.Lists; + +public class FooFixtures { + private SessionFactory sessionFactory; + + public FooFixtures(final SessionFactory sessionFactory) { + super(); + + this.sessionFactory = sessionFactory; + } + + // API + + public void createBars() { + Session session = null; + Transaction tx = null; + session = sessionFactory.openSession(); + tx = session.getTransaction(); + try { + tx.begin(); + for (int i = 156; i < 160; i++) { + final Bar bar = new Bar(); + bar.setName("Bar_" + i); + final Foo foo = new Foo("Foo_" + (i + 120)); + foo.setBar(bar); + session.save(foo); + final Foo foo2 = new Foo(null); + if (i % 2 == 0) + foo2.setName("LuckyFoo" + (i + 120)); + foo2.setBar(bar); + session.save(foo2); + bar.getFooSet().add(foo); + bar.getFooSet().add(foo2); + session.merge(bar); + } + tx.commit(); + session.flush(); + } catch (final HibernateException he) { + if (tx != null) + tx.rollback(); + System.out.println("Not able to open session"); + he.printStackTrace(); + } catch (final Exception e) { + e.printStackTrace(); + } finally { + if (session != null) + session.close(); + } + + } + + public void createFoos() { + Session session = null; + Transaction tx = null; + session = sessionFactory.openSession(); + tx = session.getTransaction(); + final List fooList = Lists.newArrayList(); + for (int i = 35; i < 46; i++) { + + final Foo foo = new Foo(); + foo.setName("Foo_" + (i + 120)); + final Bar bar = new Bar("bar_" + i); + bar.getFooSet().add(foo); + foo.setBar(bar); + fooList.add(foo); + + } + try { + tx.begin(); + for (final Foo foo : fooList) { + + session.save(foo.getBar()); + session.save(foo); + } + tx.commit(); + session.flush(); + } catch (final HibernateException he) { + if (tx != null) + tx.rollback(); + System.out.println("Not able to open session"); + he.printStackTrace(); + } catch (final Exception e) { + e.printStackTrace(); + } finally { + if (session != null) + session.close(); + } + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java new file mode 100644 index 0000000000..c9152b4d85 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java @@ -0,0 +1,185 @@ +package com.baeldung.persistence.hibernate; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.lessThan; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import javax.persistence.Tuple; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.hibernate.ScrollMode; +import org.hibernate.ScrollableResults; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +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.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.spring.PersistenceConfig; +import com.google.common.collect.Lists; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooPaginationPersistenceIntegrationTest { + + @Autowired + private IFooService fooService; + + @Autowired + private SessionFactory sessionFactory; + + private Session session; + + // tests + + @Before + public final void before() { + final int minimalNumberOfEntities = 25; + if (fooService.findAll().size() <= minimalNumberOfEntities) { + for (int i = 0; i < minimalNumberOfEntities; i++) { + fooService.create(new Foo(randomAlphabetic(6))); + } + } + + session = sessionFactory.openSession(); + } + + @After + public final void after() { + session.close(); + } + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @SuppressWarnings("unchecked") + @Test + public final void whenRetrievingPaginatedEntities_thenCorrectSize() { + final int pageNumber = 1; + final int pageSize = 10; + final List fooList = session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize) + .setMaxResults(pageSize).getResultList(); + assertThat(fooList, hasSize(pageSize)); + } + + @SuppressWarnings("unchecked") + @Test + public final void whenRetrievingAllPages_thenCorrect() { + int pageNumber = 1; + final int pageSize = 10; + + final String countQ = "Select count (f.id) from Foo f"; + final Long countResult = (Long) session.createQuery(countQ).uniqueResult(); + + final List fooList = Lists.newArrayList(); + int totalEntities = 0; + while (totalEntities < countResult) { + fooList.addAll(session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize) + .setMaxResults(pageSize).getResultList()); + totalEntities = fooList.size(); + pageNumber++; + } + } + + @SuppressWarnings("unchecked") + @Test + public final void whenRetrievingLastPage_thenCorrectSize() { + final int pageSize = 10; + + final String countQ = "Select count (f.id) from Foo f"; + final Long countResults = (Long) session.createQuery(countQ).uniqueResult(); + final int lastPageNumber = (int) ((countResults / pageSize) + 1); + + final List lastPage = session.createQuery("From Foo").setFirstResult((lastPageNumber - 1) * pageSize) + .setMaxResults(pageSize).getResultList(); + + assertThat(lastPage, hasSize(lessThan(pageSize + 1))); + } + + // testing - scrollable + + @Test + public final void givenUsingTheScrollableApi_whenRetrievingPaginatedData_thenCorrect() { + final int pageSize = 10; + final String hql = "FROM Foo f order by f.name"; + + final ScrollableResults resultScroll = session.createQuery(hql).scroll(ScrollMode.FORWARD_ONLY); + + // resultScroll.last(); + // final int totalResults = resultScroll.getRowNumber() + 1; + + resultScroll.first(); + resultScroll.scroll(0); + final List fooPage = Lists.newArrayList(); + int i = 0; + while (pageSize > i++) { + fooPage.add((Foo) resultScroll.get(0)); + if (!resultScroll.next()) { + break; + } + } + + assertThat(fooPage, hasSize(lessThan(10 + 1))); + } + + @SuppressWarnings("unchecked") + @Test + public final void givenUsingTheCriteriaApi_whenRetrievingFirstPage_thenCorrect() { + final int pageSize = 10; + + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Foo.class); + Root rootItem = criteriaItem.from(Foo.class); + criteriaItem.select(rootItem); + final List firstPage = session.createQuery(criteriaItem).setFirstResult(0).setMaxResults(pageSize) + .getResultList(); + + assertThat(firstPage, hasSize(pageSize)); + } + + @SuppressWarnings("unchecked") + @Test + public final void givenUsingTheCriteriaApi_whenRetrievingPaginatedData_thenCorrect() { + + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Tuple.class); + Root rootItem = criteriaItem.from(Foo.class); + criteriaItem.multiselect(builder.count(rootItem)); + final List itemProjected = session.createQuery(criteriaItem).getResultList(); + final Long count = (Long) itemProjected.get(0).get(0); + + int pageNumber = 1; + final int pageSize = 10; + final List fooList = Lists.newArrayList(); + + CriteriaBuilder builderFoo = session.getCriteriaBuilder(); + CriteriaQuery criteriaFoo = builderFoo.createQuery(Foo.class); + Root rootFoo = criteriaFoo.from(Foo.class); + criteriaFoo.select(rootFoo); + + int totalEntities = 0; + while (totalEntities < count.intValue()) { + fooList.addAll(session.createQuery(criteriaFoo).setFirstResult((pageNumber - 1) * pageSize) + .setMaxResults(pageSize).getResultList()); + totalEntities = fooList.size(); + pageNumber++; + } + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java new file mode 100644 index 0000000000..813fb65641 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java @@ -0,0 +1,179 @@ +package com.baeldung.persistence.hibernate; + +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Root; + +import org.hibernate.Criteria; +import org.hibernate.NullPrecedence; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +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.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@SuppressWarnings("unchecked") +public class FooSortingPersistenceIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + private Session session; + + @Before + public void before() { + session = sessionFactory.openSession(); + + session.beginTransaction(); + + final FooFixtures fooData = new FooFixtures(sessionFactory); + fooData.createBars(); + } + + @After + public void after() { + session.getTransaction().commit(); + session.close(); + } + + @Test + public final void whenHQlSortingByOneAttribute_thenPrintSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name"; + final List fooList = session.createQuery(hql).getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQlSortingByStringNullLast_thenLastNull() { + final String hql = "FROM Foo f ORDER BY f.name NULLS LAST"; + final List fooList = session.createQuery(hql).getResultList(); + + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenSortingByStringNullsFirst_thenReturnNullsFirst() { + final String hql = "FROM Foo f ORDER BY f.name NULLS FIRST"; + final List fooList = session.createQuery(hql).getResultList(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + + } + } + + @Test + public final void whenHQlSortingByOneAttribute_andOrderDirection_thenPrintSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name ASC"; + final List fooList = session.createQuery(hql).getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQlSortingByMultipleAttributes_thenSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name, f.id"; + final List fooList = session.createQuery(hql).getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQlSortingByMultipleAttributes_andOrderDirection_thenPrintSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC"; + final List fooList = session.createQuery(hql).getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQLCriteriaSortingByOneAttr_thenPrintSortedResults() { + List listOrders = new ArrayList(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Foo.class); + Root rootItem = criteriaItem.from(Foo.class); + listOrders.add(builder.asc(rootItem.get("id"))); + criteriaItem.orderBy(listOrders.toArray(new Order[] {})); + final List fooList = session.createQuery(criteriaItem).getResultList(); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + @Test + public final void whenHQLCriteriaSortingByMultipAttr_thenSortedResults() { + List listOrders = new ArrayList(); + CriteriaBuilder builder = session.getCriteriaBuilder(); + CriteriaQuery criteriaItem = builder.createQuery(Foo.class); + Root rootItem = criteriaItem.from(Foo.class); + listOrders.add(builder.asc(rootItem.get("name"))); + listOrders.add(builder.asc(rootItem.get("id"))); + criteriaItem.orderBy(listOrders.toArray(new Order[] {})); + final List fooList = session.createQuery(criteriaItem).getResultList(); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + /*@Test + public final void whenCriteriaSortingStringNullsLastAsc_thenNullsLast() { + final Criteria criteria = session.createCriteria(Foo.class, "FOO"); + criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST)); + final List fooList = criteria.list(); + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + @Test + public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() { + final Criteria criteria = session.createCriteria(Foo.class, "FOO"); + criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST)); + final List fooList = criteria.list(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + }*/ + + @Test + public final void whenSortingBars_thenBarsWithSortedFoos() { + final String hql = "FROM Bar b ORDER BY b.id"; + final List barList = session.createQuery(hql).getResultList(); + for (final Bar bar : barList) { + final Set fooSet = bar.getFooSet(); + System.out.println("Bar Id:" + bar.getId()); + for (final Foo foo : fooSet) { + System.out.println("FooName:" + foo.getName()); + } + } + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java new file mode 100644 index 0000000000..b6cde868d3 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java @@ -0,0 +1,285 @@ +package com.baeldung.persistence.save; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import javax.persistence.PersistenceException; + +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.TransactionException; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.HSQLDialect; +import org.hibernate.service.ServiceRegistry; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.persistence.model.Person; + +/** + * Testing specific implementation details for different methods: persist, save, + * merge, update, saveOrUpdate. + */ +public class SaveMethodsTest { + + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + Configuration configuration = new Configuration().addAnnotatedClass(Person.class) + .setProperty("hibernate.dialect", HSQLDialect.class.getName()) + .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) + .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test") + .setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "") + .setProperty("hibernate.hbm2ddl.auto", "update"); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings( + configuration.getProperties()).build(); + sessionFactory = configuration.buildSessionFactory(serviceRegistry); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void whenPersistTransient_thenSavedToDatabaseOnCommit() { + + Person person = new Person(); + person.setName("John"); + session.persist(person); + + session.getTransaction().commit(); + session.close(); + + session = sessionFactory.openSession(); + session.beginTransaction(); + + assertNotNull(session.get(Person.class, person.getId())); + + } + + @Test + public void whenPersistPersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + + session.persist(person); + Long id1 = person.getId(); + + session.persist(person); + Long id2 = person.getId(); + + assertEquals(id1, id2); + } + + @Test(expected = PersistenceException.class) + public void whenPersistDetached_thenThrowsException() { + + Person person = new Person(); + person.setName("John"); + session.persist(person); + session.evict(person); + + session.persist(person); + + } + + @Test + public void whenSaveTransient_thenIdGeneratedImmediately() { + + Person person = new Person(); + person.setName("John"); + + assertNull(person.getId()); + + Long id = (Long) session.save(person); + + assertNotNull(id); + + session.getTransaction().commit(); + session.close(); + + assertEquals(id, person.getId()); + + session = sessionFactory.openSession(); + session.beginTransaction(); + + assertNotNull(session.get(Person.class, person.getId())); + + } + + @Test + public void whenSavePersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + Long id1 = (Long) session.save(person); + Long id2 = (Long) session.save(person); + assertEquals(id1, id2); + + } + + @Test + public void whenSaveDetached_thenNewInstancePersisted() { + + Person person = new Person(); + person.setName("John"); + Long id1 = (Long) session.save(person); + session.evict(person); + + Long id2 = (Long) session.save(person); + assertNotEquals(id1, id2); + + } + + @Test + public void whenMergeDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.flush(); + session.evict(person); + + person.setName("Mary"); + Person mergedPerson = (Person) session.merge(person); + + assertNotSame(person, mergedPerson); + assertEquals("Mary", mergedPerson.getName()); + + } + + @Test + public void whenMergeTransient_thenNewEntitySavedToDatabase() { + + Person person = new Person(); + person.setName("John"); + Person mergedPerson = (Person) session.merge(person); + + session.getTransaction().commit(); + session.beginTransaction(); + + assertNull(person.getId()); + assertNotNull(mergedPerson.getId()); + + } + + @Test + public void whenMergePersistent_thenReturnsSameObject() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + + Person mergedPerson = (Person) session.merge(person); + + assertSame(person, mergedPerson); + + } + + @Test + public void whenUpdateDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.evict(person); + + person.setName("Mary"); + session.update(person); + assertEquals("Mary", person.getName()); + + } + + @Test(expected = HibernateException.class) + public void whenUpdateTransient_thenThrowsException() { + + Person person = new Person(); + person.setName("John"); + session.update(person); + + } + + @Test + public void whenUpdatePersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + + session.update(person); + + } + + @Test + public void whenSaveOrUpdateDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.evict(person); + + person.setName("Mary"); + session.saveOrUpdate(person); + assertEquals("Mary", person.getName()); + + } + + @Test + public void whenSaveOrUpdateTransient_thenSavedToDatabaseOnCommit() { + + Person person = new Person(); + person.setName("John"); + session.saveOrUpdate(person); + + session.getTransaction().commit(); + session.close(); + + session = sessionFactory.openSession(); + session.beginTransaction(); + + assertNotNull(session.get(Person.class, person.getId())); + + } + + @Test + public void whenSaveOrUpdatePersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + + session.saveOrUpdate(person); + + } + + @After + public void tearDown() { + try{ + session.getTransaction().commit(); + session.close(); + }catch(TransactionException ex){ + ex.printStackTrace(); + } + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java new file mode 100644 index 0000000000..c77f5dfb95 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +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.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooServiceBasicPersistenceIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + @Autowired + private IFooService fooService; + + private Session session; + + // tests + + @Before + public final void before() { + session = sessionFactory.openSession(); + } + + @After + public final void after() { + session.close(); + } + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + fooService.create(new Foo(randomAlphabetic(6))); + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..b82d4621ab --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java @@ -0,0 +1,63 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooServicePersistenceIntegrationTest { + + @Autowired + @Qualifier("fooHibernateService") + private IFooService service; + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenEntityIsCreated_thenNoExceptions() { + service.create(new Foo(randomAlphabetic(6))); + } + + @Test(expected = DataIntegrityViolationException.class) + @Ignore("work in progress") + public final void whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo()); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenEntityWithLongNameIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + + @Test(expected = InvalidDataAccessApiUsageException.class) + @Ignore("Right now, persist has saveOrUpdate semantics, so this will no longer fail") + public final void whenSameEntityIsCreatedTwice_thenDataException() { + final Foo entity = new Foo(randomAlphabetic(8)); + service.create(entity); + service.create(entity); + } + + @Test(expected = DataAccessException.class) + public final void temp_whenInvalidEntityIsCreated_thenDataException() { + service.create(new Foo(randomAlphabetic(2048))); + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java new file mode 100644 index 0000000000..cfd3844079 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java @@ -0,0 +1,114 @@ +package com.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.exception.SQLGrammarException; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooStoredProceduresIntegrationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresIntegrationTest.class); + + @Autowired + private SessionFactory sessionFactory; + + @Autowired + private IFooService fooService; + + private Session session; + + @Before + public final void before() { + session = sessionFactory.openSession(); + Assume.assumeTrue(getAllFoosExists()); + Assume.assumeTrue(getFoosByNameExists()); + } + + private boolean getFoosByNameExists() { + try { + session.createQuery("CALL GetAllFoos()", Foo.class).getResultList(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e); + return false; + } + } + + private boolean getAllFoosExists() { + try { + session.createQuery("CALL GetAllFoos()", Foo.class).getResultList(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e); + return false; + } + } + + @After + public final void after() { + session.close(); + } + + @Test + public final void getAllFoosUsingStoredProcedures() { + + fooService.create(new Foo(randomAlphabetic(6))); + + // Stored procedure getAllFoos using createSQLQuery + List allFoos = session.createQuery("CALL GetAllFoos()", Foo.class).getResultList(); + for (Foo foo : allFoos) { + LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName()); + } + assertEquals(allFoos.size(), fooService.findAll().size()); + + // Stored procedure getAllFoos using a Named Query + @SuppressWarnings("unchecked") + List allFoos2 = session.getNamedQuery("callGetAllFoos").getResultList(); + for (Foo foo : allFoos2) { + LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName()); + } + assertEquals(allFoos2.size(), fooService.findAll().size()); + } + + @Test + public final void getFoosByNameUsingStoredProcedures() { + + fooService.create(new Foo("NewFooName")); + + // Stored procedure getFoosByName using createSQLQuery() + List allFoosByName = session.createQuery("CALL GetFoosByName(:fooName)", Foo.class) + .setParameter("fooName", "NewFooName").getResultList(); + for (Foo foo : allFoosByName) { + LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString()); + } + + // Stored procedure getFoosByName using getNamedQuery() + @SuppressWarnings("unchecked") + List allFoosByName2 = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName") + .getResultList(); + for (Foo foo : allFoosByName2) { + LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString()); + } + + } +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java new file mode 100644 index 0000000000..9e8c4aba92 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java @@ -0,0 +1,69 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.model.Parent; +import com.baeldung.spring.PersistenceConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class ParentServicePersistenceIntegrationTest { + + @Autowired + private IParentService service; + + @Autowired + private IChildService childService; + + // tests + + @Test + public final void whenContextIsBootstrapped_thenNoExceptions() { + // + } + + @Test + public final void whenOneToOneEntitiesAreCreated_thenNoExceptions() { + final Child childEntity = new Child(); + childService.create(childEntity); + + final Parent parentEntity = new Parent(childEntity); + service.create(parentEntity); + + System.out.println("Child = " + childService.findOne(childEntity.getId())); + System.out.println("Child - parent = " + childService.findOne(childEntity.getId()).getParent()); + + System.out.println("Parent = " + service.findOne(parentEntity.getId())); + System.out.println("Parent - child = " + service.findOne(parentEntity.getId()).getChild()); + } + + @Test(expected = DataIntegrityViolationException.class) + public final void whenChildIsDeletedWhileParentStillHasForeignKeyToIt_thenDataException() { + final Child childEntity = new Child(); + childService.create(childEntity); + + final Parent parentEntity = new Parent(childEntity); + service.create(parentEntity); + + childService.delete(childEntity); + } + + @Test + public final void whenChildIsDeletedAfterTheParent_thenNoExceptions() { + final Child childEntity = new Child(); + childService.create(childEntity); + + final Parent parentEntity = new Parent(childEntity); + service.create(parentEntity); + + service.delete(parentEntity); + childService.delete(childEntity); + } + +} diff --git a/spring-hibernate5/src/test/resources/.gitignore b/spring-hibernate5/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-hibernate5/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml b/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml new file mode 100644 index 0000000000..9e0109aae2 --- /dev/null +++ b/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/test/resources/criteria.cfg.xml b/spring-hibernate5/src/test/resources/criteria.cfg.xml new file mode 100644 index 0000000000..5bc3a32077 --- /dev/null +++ b/spring-hibernate5/src/test/resources/criteria.cfg.xml @@ -0,0 +1,16 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + root + org.hibernate.dialect.MySQLDialect + true + + + \ No newline at end of file diff --git a/spring-hibernate5/src/test/resources/fetching.cfg.xml b/spring-hibernate5/src/test/resources/fetching.cfg.xml new file mode 100644 index 0000000000..c47b062a2f --- /dev/null +++ b/spring-hibernate5/src/test/resources/fetching.cfg.xml @@ -0,0 +1,18 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + root + org.hibernate.dialect.MySQLDialect + true + + + + + \ No newline at end of file diff --git a/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml b/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml new file mode 100644 index 0000000000..2e252e9307 --- /dev/null +++ b/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml @@ -0,0 +1,18 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + root + org.hibernate.dialect.MySQLDialect + true + + + + + \ No newline at end of file diff --git a/spring-jersey/README.md b/spring-jersey/README.md index 2767ceb9a7..8b2eecc0e1 100644 --- a/spring-jersey/README.md +++ b/spring-jersey/README.md @@ -1,3 +1,5 @@ ========= ## REST API with Jersey & Spring Example Project +- [REST API with Jersey and Spring](http://www.baeldung.com/jersey-rest-api-with-spring) +- [JAX-RS Client with Jersey](http://www.baeldung.com/jersey-jax-rs-client) diff --git a/spring-mobile/README.md b/spring-mobile/README.md new file mode 100644 index 0000000000..e3d23bcda6 --- /dev/null +++ b/spring-mobile/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [A Guide to Spring Mobile](http://www.baeldung.com/spring-mobile) + diff --git a/spring-mvc-email/README.md b/spring-mvc-email/README.md index 0de6532393..aa880188d7 100644 --- a/spring-mvc-email/README.md +++ b/spring-mvc-email/README.md @@ -1,3 +1,7 @@ +## Relevant articles: + +- [Guide to Spring Email](http://www.baeldung.com/spring-email) + ## Spring MVC Email Example Spring MVC project to send email from web form. @@ -10,4 +14,4 @@ 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 +Follow UI links to send simple email, email using template or email with attachment. diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index 0f267c5ec9..4d3e58558b 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -18,3 +18,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml) - [Circular Dependencies in Spring](http://www.baeldung.com/circular-dependencies-in-spring) - [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit) +- [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts) +- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings) +- [Uploading and Displaying Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files) diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md new file mode 100644 index 0000000000..ffb02c846a --- /dev/null +++ b/spring-mvc-simple/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [HandlerAdapters in Spring MVC](http://www.baeldung.com/spring-mvc-handler-adapters) diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml index f0e4bbff55..86eb17da64 100644 --- a/spring-mvc-xml/pom.xml +++ b/spring-mvc-xml/pom.xml @@ -116,7 +116,13 @@ com.maxmind.geoip2 geoip2 ${geoip2.version} - + + + com.fasterxml.jackson.core + jackson-databind + + + diff --git a/spring-reactor/README.md b/spring-reactor/README.md new file mode 100644 index 0000000000..0da2d6be51 --- /dev/null +++ b/spring-reactor/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to Spring Reactor](http://www.baeldung.com/spring-reactor) diff --git a/spring-remoting/README.md b/spring-remoting/README.md index 1aafdaf6f5..41bbd59f01 100644 --- a/spring-remoting/README.md +++ b/spring-remoting/README.md @@ -1,7 +1,8 @@ -## Spring Remoting Tutorials Project +## Spring Remoting Tutorials ### Relevant Articles - [Intro to Spring Remoting with HTTP Invokers](http://www.baeldung.com/spring-remoting-http-invoker) +- [Spring Remoting with Hessian and Burlap](http://www.baeldung.com/spring-remoting-hessian-burlap) ### Overview This Maven project contains the Java source code for various modules used in the Spring Remoting series of articles. diff --git a/spring-remoting/pom.xml b/spring-remoting/pom.xml index a43dd52a3e..52d670a726 100644 --- a/spring-remoting/pom.xml +++ b/spring-remoting/pom.xml @@ -3,16 +3,17 @@ 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"> 4.0.0 + com.baeldung + spring-remoting + pom + 1.0-SNAPSHOT + spring-remoting + Parent for all projects related to Spring Remoting. org.springframework.boot spring-boot-starter-parent 1.4.3.RELEASE - com.baeldung - spring-remoting - 1.0-SNAPSHOT - Parent for all projects related to Spring Remoting. - pom 1.8 @@ -34,6 +35,7 @@ remoting-http + remoting-hessian-burlap \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/README.md b/spring-remoting/remoting-hessian-burlap/README.md new file mode 100644 index 0000000000..bf90c9676f --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/README.md @@ -0,0 +1,9 @@ +## Spring Remoting with Hessian and Burlap Tutorial + +### Relevant Articles +- [Spring Remoting with Hessian and Burlap](http://www.baeldung.com/spring-remoting-hessian-burlap) + +### Overview +This Maven project contains the Java source code for the Hessian and Burlap modules + used in the [Spring Remoting](https://github.com/eugenp/tutorials/tree/master/spring-remoting) + series of articles. diff --git a/spring-remoting/remoting-hessian-burlap/client/pom.xml b/spring-remoting/remoting-hessian-burlap/client/pom.xml new file mode 100644 index 0000000000..1ae9b10019 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/pom.xml @@ -0,0 +1,59 @@ + + + + remoting-hessian-burlap + com.baeldung + 1.0-SNAPSHOT + + 4.0.0 + + spring-remoting-hessian-burlap-client + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + ${project.groupId} + api + + + com.caucho + hessian + 4.0.38 + + + + + ${project.groupId} + remoting-hessian-burlap-server + ${project.version} + test + + + javax.servlet + javax.servlet-api + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-tomcat + test + + + + \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java new file mode 100644 index 0000000000..477c29eb26 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java @@ -0,0 +1,28 @@ +package com.baeldung.client; + +import com.baeldung.api.BookingException; +import com.baeldung.api.CabBookingService; +import org.springframework.boot.SpringApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.remoting.caucho.BurlapProxyFactoryBean; + +import static java.lang.System.out; + +@Configuration +public class BurlapClient { + + @Bean + public BurlapProxyFactoryBean burlapInvoker() { + BurlapProxyFactoryBean invoker = new BurlapProxyFactoryBean(); + invoker.setServiceUrl("http://localhost:8080/b_booking"); + invoker.setServiceInterface(CabBookingService.class); + return invoker; + } + + public static void main(String[] args) throws BookingException { + CabBookingService service = SpringApplication.run(BurlapClient.class, args).getBean(CabBookingService.class); + out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037")); + } + +} diff --git a/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java new file mode 100644 index 0000000000..b5f366094e --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java @@ -0,0 +1,28 @@ +package com.baeldung.client; + +import com.baeldung.api.BookingException; +import com.baeldung.api.CabBookingService; +import org.springframework.boot.SpringApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.remoting.caucho.HessianProxyFactoryBean; + +import static java.lang.System.out; + +@Configuration +public class HessianClient { + + @Bean + public HessianProxyFactoryBean hessianInvoker() { + HessianProxyFactoryBean invoker = new HessianProxyFactoryBean(); + invoker.setServiceUrl("http://localhost:8080/booking"); + invoker.setServiceInterface(CabBookingService.class); + return invoker; + } + + public static void main(String[] args) throws BookingException { + CabBookingService service = SpringApplication.run(HessianClient.class, args).getBean(CabBookingService.class); + out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037")); + } + +} diff --git a/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java b/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java new file mode 100644 index 0000000000..373701f714 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java @@ -0,0 +1,74 @@ +package com.baeldung.client; + +import com.baeldung.api.Booking; +import com.baeldung.api.BookingException; +import com.baeldung.api.CabBookingService; +import com.baeldung.server.Server; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static java.lang.Thread.sleep; + +@SpringBootTest(classes = {BurlapClient.class, HessianClient.class}) +@RunWith(SpringRunner.class) +public class CabBookingServiceTest { + + static Logger log = LoggerFactory.getLogger(CabBookingServiceTest.class); + @Autowired @Qualifier("burlapInvoker") CabBookingService burlapClient; + @Autowired @Qualifier("hessianInvoker") CabBookingService hessianClient; + static Thread serverThread; + + @BeforeClass + public static void startServer() throws InterruptedException { + serverThread = serverThread(); + log.info("Starting server."); + serverThread.start(); + // increase this enough to let the server start + sleep(6000); + } + + @org.junit.Test + public void bookACabWithBurlapClient() throws InterruptedException { + bookACab(this.burlapClient); + } + + @org.junit.Test + public void bookACabWithHessianClient() throws InterruptedException { + bookACab(this.hessianClient); + } + + private void bookACab(CabBookingService burlapClient) { + Booking booking; + try { + booking = burlapClient.bookRide("Duomo place"); + log.info("Booking success: {}", booking); + } catch (BookingException e) { + log.info("Booking failed: {}", e.getMessage()); + } + } + + @AfterClass + public static void stopServer() throws InterruptedException { + serverThread.interrupt(); + serverThread.join(); + log.info("Server terminated."); + } + + static Thread serverThread() { + Thread serverThread = new Thread(()-> { + log.info("Starting Burlap and Hessian server"); + Server.main(new String[]{}); + log.info("Burlap and Hessian server terminated"); + }); + serverThread.setDaemon(true); + return serverThread; + } + +} diff --git a/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties b/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties new file mode 100644 index 0000000000..13577dc391 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties @@ -0,0 +1 @@ +application.properties=9999 \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/pom.xml b/spring-remoting/remoting-hessian-burlap/pom.xml new file mode 100644 index 0000000000..682e460880 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/pom.xml @@ -0,0 +1,20 @@ + + + + spring-remoting + com.baeldung + 1.0-SNAPSHOT + + pom + + server + client + + 4.0.0 + + remoting-hessian-burlap + + + \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/server/pom.xml b/spring-remoting/remoting-hessian-burlap/server/pom.xml new file mode 100644 index 0000000000..f1fed73ed8 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/server/pom.xml @@ -0,0 +1,30 @@ + + + + remoting-hessian-burlap + com.baeldung + 1.0-SNAPSHOT + + 4.0.0 + + remoting-hessian-burlap-server + + + + com.baeldung + spring-remoting-http-server + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + + + com.caucho + hessian + 4.0.38 + + + \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java b/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java new file mode 100644 index 0000000000..9b7e463871 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java @@ -0,0 +1,37 @@ +package com.baeldung.server; + +import com.baeldung.api.CabBookingService; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.remoting.caucho.BurlapServiceExporter; +import org.springframework.remoting.caucho.HessianServiceExporter; +import org.springframework.remoting.support.RemoteExporter; + +@Configuration @ComponentScan @EnableAutoConfiguration public class Server { + + @Bean CabBookingService bookingService() { + return new CabBookingServiceImpl(); + } + + @Bean(name = "/booking") RemoteExporter hessianService(CabBookingService service) { + HessianServiceExporter exporter = new HessianServiceExporter(); + exporter.setService(bookingService()); + exporter.setServiceInterface(CabBookingService.class); + return exporter; + } + + @Bean(name = "/b_booking") RemoteExporter burlapService(CabBookingService service) { + BurlapServiceExporter exporter = new BurlapServiceExporter(); + exporter.setService(bookingService()); + exporter.setServiceInterface(CabBookingService.class); + return exporter; + } + + public static void main(String[] args) { + SpringApplication.run(Server.class, args); + } + +} \ No newline at end of file diff --git a/spring-rest-angular/pom.xml b/spring-rest-angular/pom.xml index 099867d19b..b6bc95df81 100644 --- a/spring-rest-angular/pom.xml +++ b/spring-rest-angular/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.4.RELEASE + 1.5.1.RELEASE diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java b/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java index b1aafb583a..566d95da00 100644 --- a/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java +++ b/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java @@ -3,6 +3,7 @@ package org.baeldung.web.dao; import org.baeldung.web.entity.Student; import org.springframework.data.jpa.repository.JpaRepository; -public interface StudentRepository extends JpaRepository { +public interface StudentRepository extends JpaRepository +{ } diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java b/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java index df1240f270..e0f6002733 100644 --- a/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java +++ b/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java @@ -2,7 +2,7 @@ package org.baeldung.web.main; import javax.sql.DataSource; -import org.springframework.boot.orm.jpa.EntityScan; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/spring-rest-angular/src/main/webapp/view/app.js b/spring-rest-angular/src/main/webapp/view/app.js index a41026d2c3..b56497807c 100644 --- a/spring-rest-angular/src/main/webapp/view/app.js +++ b/spring-rest-angular/src/main/webapp/view/app.js @@ -1,12 +1,12 @@ var app = angular.module('app', ['ui.grid','ui.grid.pagination']); - + app.controller('StudentCtrl', ['$scope','StudentService', function ($scope,StudentService) { var paginationOptions = { pageNumber: 1, pageSize: 5, sort: null - }; - + }; + StudentService.getStudents(paginationOptions.pageNumber, paginationOptions.pageSize).success(function(data){ $scope.gridOptions.data = data.content; @@ -53,4 +53,4 @@ app.service('StudentService',['$http', function ($http) { getStudents:getStudents }; -}]); \ No newline at end of file +}]); diff --git a/spring-security-cache-control/README.md b/spring-security-cache-control/README.md new file mode 100644 index 0000000000..4b0bab72cb --- /dev/null +++ b/spring-security-cache-control/README.md @@ -0,0 +1,6 @@ +========= + +## Spring Security Cache Control + +### Relevant Articles: +- [Spring Security – Cache Control Headers](http://www.baeldung.com/spring-security-cache-control-headers) diff --git a/spring-security-mvc-login/pom.xml b/spring-security-mvc-login/pom.xml index 965f4fe1de..3809dc9f26 100644 --- a/spring-security-mvc-login/pom.xml +++ b/spring-security-mvc-login/pom.xml @@ -152,6 +152,19 @@ test + + org.springframework + spring-test + ${org.springframework.version} + test + + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + + @@ -222,7 +235,7 @@ - 4.3.5.RELEASE + 4.3.6.RELEASE 4.2.1.RELEASE diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/controller/SecuredResourceController.java b/spring-security-mvc-login/src/main/java/org/baeldung/controller/SecuredResourceController.java new file mode 100644 index 0000000000..4b68eee983 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/controller/SecuredResourceController.java @@ -0,0 +1,17 @@ +package org.baeldung.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Controller +public class SecuredResourceController { + + @RequestMapping("/secured") + public void secureResource(HttpServletRequest request, HttpServletResponse response) { + System.out.println("accessing secured resource"); + } + +} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/security/RefererAuthenticationSuccessHandler.java b/spring-security-mvc-login/src/main/java/org/baeldung/security/RefererAuthenticationSuccessHandler.java new file mode 100644 index 0000000000..5b025d9fd1 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/security/RefererAuthenticationSuccessHandler.java @@ -0,0 +1,13 @@ +package org.baeldung.security; + +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; + +public class RefererAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + public RefererAuthenticationSuccessHandler() { + super(); + setUseReferer(true); + } + +} \ No newline at end of file diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/RedirectionSecurityConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/RedirectionSecurityConfig.java new file mode 100644 index 0000000000..b68e7eab50 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/RedirectionSecurityConfig.java @@ -0,0 +1,44 @@ +package org.baeldung.spring; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +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.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; + +@Configuration +//@ImportResource({ "classpath:RedirectionWebSecurityConfig.xml" }) +@EnableWebSecurity +@Profile("!https") +public class RedirectionSecurityConfig extends WebSecurityConfigurerAdapter { + + public RedirectionSecurityConfig() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("user1") + .password("user1Pass") + .roles("USER"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/login*") + .permitAll() + .anyRequest() + .authenticated() + .and() + .formLogin() + .successHandler(new SavedRequestAwareAuthenticationSuccessHandler()); + //.successHandler(new RefererAuthenticationSuccessHandler()) + } + +} diff --git a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml new file mode 100644 index 0000000000..231b5ab57e --- /dev/null +++ b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-security-mvc-login/src/test/java/org/baeldung/security/RedirectionSecurityIntegrationTest.java b/spring-security-mvc-login/src/test/java/org/baeldung/security/RedirectionSecurityIntegrationTest.java new file mode 100644 index 0000000000..1d7fae8b60 --- /dev/null +++ b/spring-security-mvc-login/src/test/java/org/baeldung/security/RedirectionSecurityIntegrationTest.java @@ -0,0 +1,94 @@ +package org.baeldung.security; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/RedirectionWebSecurityConfig.xml", "/mvc-servlet.xml" }) +@WebAppConfiguration +public class RedirectionSecurityIntegrationTest { + + @Autowired private WebApplicationContext context; + + @Autowired private UserDetailsService userDetailsService; + + private MockMvc mvc; + private UserDetails userDetails; + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .apply(springSecurity()) + .build(); + userDetails = userDetailsService.loadUserByUsername("user1"); + } + + @Test + public void givenSecuredResource_whenAccessUnauthenticated_thenRequiresAuthentication() throws Exception { + mvc + .perform(get("/secured")) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrlPattern("**/login")); + + } + + @Test + public void givenCredentials_whenAccessSecuredResource_thenSuccess() throws Exception { + mvc + .perform(get("/secured").with(user(userDetails))) + .andExpect(status().isOk()); + } + + @Test + public void givenAccessSecuredResource_whenAuthenticated_thenRedirectedBack() throws Exception { + MockHttpServletRequestBuilder securedResourceAccess = get("/secured"); + MvcResult unauthenticatedResult = mvc + .perform(securedResourceAccess) + .andExpect(status().is3xxRedirection()) + .andReturn(); + + MockHttpSession session = (MockHttpSession) unauthenticatedResult + .getRequest() + .getSession(); + String loginUrl = unauthenticatedResult + .getResponse() + .getRedirectedUrl(); + mvc + .perform(post(loginUrl) + .param("username", userDetails.getUsername()) + .param("password", userDetails.getPassword()) + .session(session) + .with(csrf())) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrlPattern("**/secured")) + .andReturn(); + + mvc + .perform(securedResourceAccess.session(session)) + .andExpect(status().isOk()); + + } + +} diff --git a/spring-security-mvc-login/src/test/resources/mvc-servlet.xml b/spring-security-mvc-login/src/test/resources/mvc-servlet.xml new file mode 100644 index 0000000000..aa5488b116 --- /dev/null +++ b/spring-security-mvc-login/src/test/resources/mvc-servlet.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md index a1dfa32c6d..92b759a66a 100644 --- a/spring-security-rest/README.md +++ b/spring-security-rest/README.md @@ -13,3 +13,4 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Custom Error Message Handling for REST API](http://www.baeldung.com/global-error-handler-in-a-spring-rest-api) - [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial) - [Spring Security Context Propagation with @Async](http://www.baeldung.com/spring-security-async-principal-propagation) +- [Servlet 3 Async Support with Spring MVC and Spring Security](http://www.baeldung.com/spring-mvc-async-security) diff --git a/spring-security-stormpath/pom.xml b/spring-security-stormpath/pom.xml new file mode 100644 index 0000000000..44c6595e64 --- /dev/null +++ b/spring-security-stormpath/pom.xml @@ -0,0 +1,85 @@ + + 4.0.0 + com.baeldung + spring-security-stormpath + war + 1.0-SNAPSHOT + spring-security-stormpath + http://maven.apache.org + + + + abhinabkanrar@gmail.com + Abhinab Kanrar + https://github.com/AbhinabKanrar + abhinabkanrar + + + + + UTF-8 + UTF-8 + 1.8 + + + + org.springframework.boot + spring-boot-starter-parent + 1.5.1.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + com.stormpath.spring + stormpath-default-spring-boot-starter + 1.5.4 + + + + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release + + + + + spring-security-stormpath + + + src/main/resources + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + repackage + + + + + + + + diff --git a/spring-security-stormpath/src/main/java/com/baeldung/Application.java b/spring-security-stormpath/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..3d1409eaeb --- /dev/null +++ b/spring-security-stormpath/src/main/java/com/baeldung/Application.java @@ -0,0 +1,25 @@ +/** + * + */ +package com.baeldung; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author abhinab + * + */ +@SpringBootApplication +public class Application implements CommandLineRunner { + + @Override + public void run(String... args) throws Exception { + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-stormpath/src/main/java/com/baeldung/security/SecurityConfiguration.java b/spring-security-stormpath/src/main/java/com/baeldung/security/SecurityConfiguration.java new file mode 100644 index 0000000000..5d75ecea8a --- /dev/null +++ b/spring-security-stormpath/src/main/java/com/baeldung/security/SecurityConfiguration.java @@ -0,0 +1,24 @@ +/** + * + */ +package com.baeldung.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +import static com.stormpath.spring.config.StormpathWebSecurityConfigurer.stormpath; + +/** + * @author abhinab + * + */ +@Configuration +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.apply(stormpath()); + } + +} diff --git a/spring-security-stormpath/src/main/resources/application.properties b/spring-security-stormpath/src/main/resources/application.properties new file mode 100644 index 0000000000..64a9ca456c --- /dev/null +++ b/spring-security-stormpath/src/main/resources/application.properties @@ -0,0 +1,6 @@ +security.basic.enabled = false + +stormpath.web.stormpathFilter.order = 0 + +stormpath.client.apiKey.id = 668HU0EOZQ7F4MT53ND2HSGBA +stormpath.client.apiKey.secret = RPTaYX07csTJR0AMKjM462KRdiP6q037kBWoDrBC3DI diff --git a/spring-sleuth/README.md b/spring-sleuth/README.md new file mode 100644 index 0000000000..47aa126939 --- /dev/null +++ b/spring-sleuth/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Spring Cloud Sleuth in a Monolith Application](http://www.baeldung.com/spring-cloud-sleuth-single-application) diff --git a/static-analysis/README.md b/static-analysis/README.md new file mode 100644 index 0000000000..74cc64b90d --- /dev/null +++ b/static-analysis/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to PMD](http://www.baeldung.com/pmd) diff --git a/struts2/pom.xml b/struts2/pom.xml index 983f18903b..25a374549d 100644 --- a/struts2/pom.xml +++ b/struts2/pom.xml @@ -4,7 +4,7 @@ com.baeldung MyStrutsApp 0.0.1-SNAPSHOT - war + pom struts src/main/java diff --git a/testng/pom.xml b/testng/pom.xml index 5cf8ab06f3..83b32bb84d 100644 --- a/testng/pom.xml +++ b/testng/pom.xml @@ -1,121 +1,121 @@ - 4.0.0 - com.baeldung - testng - 0.1.0-SNAPSHOT - jar - testng + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + testng + 0.1.0-SNAPSHOT + jar + testng - + - + - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + - + - - org.testng - testng - ${testng.version} - test - + + org.testng + testng + ${testng.version} + test + - + - - testng - - - src/main/resources - true - - - - - src/main/resources - true - - + + testng + + + src/main/resources + true + + + + + src/main/resources + true + + - + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - **/*IntegrationTest.java - **/*LongRunningUnitTest.java - **/*ManualTest.java - - - src\test\resources\parametrized_testng.xml - src\test\resources\test_group.xml - src\test\resources\test_setup.xml - src\test\resources\test_suite.xml - + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + + + src\test\resources\parametrized_testng.xml + src\test\resources\test_group.xml + src\test\resources\test_setup.xml + src\test\resources\test_suite.xml + - true - - + true + + - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/libs + + + + + - + - + - - 1.7.21 - 1.1.7 + + 1.7.21 + 1.1.7 - - 6.10 + + 6.10 - - 3.6.0 - 2.19.1 + + 3.6.0 + 2.19.1 - + \ No newline at end of file diff --git a/testng/src/test/java/baeldung/com/MultiThreadedTests.java b/testng/src/test/java/baeldung/com/MultiThreadedTests.java index 48096b8c20..4476eaa7a0 100644 --- a/testng/src/test/java/baeldung/com/MultiThreadedTests.java +++ b/testng/src/test/java/baeldung/com/MultiThreadedTests.java @@ -4,11 +4,11 @@ import org.testng.Assert; import org.testng.annotations.Test; public class MultiThreadedTests { - + @Test(threadPoolSize = 5, invocationCount = 10, timeOut = 1000) - public void givenMethod_whenRunInThreads_thenCorrect(){ + public void givenMethod_whenRunInThreads_thenCorrect() { int count = Thread.activeCount(); - Assert.assertTrue(count>1); + Assert.assertTrue(count > 1); } } diff --git a/testng/src/test/java/baeldung/com/TestGroup.java b/testng/src/test/java/baeldung/com/TestGroup.java index 014fad7f8b..a592000bed 100644 --- a/testng/src/test/java/baeldung/com/TestGroup.java +++ b/testng/src/test/java/baeldung/com/TestGroup.java @@ -6,39 +6,39 @@ import org.testng.annotations.Test; public class TestGroup { - @BeforeGroups("database") - public void setupDB() { - System.out.println("setupDB()"); - } + @BeforeGroups("database") + public void setupDB() { + System.out.println("setupDB()"); + } - @AfterGroups("database") - public void cleanDB() { - System.out.println("cleanDB()"); - } + @AfterGroups("database") + public void cleanDB() { + System.out.println("cleanDB()"); + } - @Test(groups= "selenium-test") - public void runSelenium() { - System.out.println("runSelenium()"); - } + @Test(groups = "selenium-test") + public void runSelenium() { + System.out.println("runSelenium()"); + } - @Test(groups= "selenium-test") - public void runSelenium1() { - System.out.println("runSelenium()1"); - } + @Test(groups = "selenium-test") + public void runSelenium1() { + System.out.println("runSelenium()1"); + } - @Test(groups = "database") - public void testConnectOracle() { - System.out.println("testConnectOracle()"); - } + @Test(groups = "database") + public void testConnectOracle() { + System.out.println("testConnectOracle()"); + } - @Test(groups = "database") - public void testConnectMsSQL() { - System.out.println("testConnectMsSQL"); - } + @Test(groups = "database") + public void testConnectMsSQL() { + System.out.println("testConnectMsSQL"); + } - @Test(dependsOnGroups = {"database","selenium-test"}) - public void runFinal() { - System.out.println("runFinal"); - } + @Test(dependsOnGroups = {"database", "selenium-test"}) + public void runFinal() { + System.out.println("runFinal"); + } } \ No newline at end of file diff --git a/testng/src/test/java/com/baeldung/reports/CustomisedListener.java b/testng/src/test/java/com/baeldung/reports/CustomisedListener.java index 179ca5f736..e8338c941d 100644 --- a/testng/src/test/java/com/baeldung/reports/CustomisedListener.java +++ b/testng/src/test/java/com/baeldung/reports/CustomisedListener.java @@ -13,25 +13,25 @@ public class CustomisedListener implements ITestListener { public void onFinish(ITestContext arg0) { LOGGER.info("PASSED TEST CASES"); arg0.getPassedTests() - .getAllResults() - .stream() - .forEach(result -> { - LOGGER.info(result.getName()); - }); + .getAllResults() + .stream() + .forEach(result -> { + LOGGER.info(result.getName()); + }); LOGGER.info("FAILED TEST CASES"); arg0.getFailedTests() - .getAllResults() - .stream() - .forEach(result -> { - LOGGER.info(result.getName()); - }); - LOGGER.info("Test completed on: "+arg0.getEndDate().toString()); + .getAllResults() + .stream() + .forEach(result -> { + LOGGER.info(result.getName()); + }); + LOGGER.info("Test completed on: " + arg0.getEndDate().toString()); } @Override public void onStart(ITestContext arg0) { LOGGER.info("Started testing on: " + arg0.getStartDate() - .toString()); + .toString()); } @Override diff --git a/testng/src/test/java/com/baeldung/reports/CustomisedReports.java b/testng/src/test/java/com/baeldung/reports/CustomisedReports.java index e59ecbd79b..07ba2162cc 100644 --- a/testng/src/test/java/com/baeldung/reports/CustomisedReports.java +++ b/testng/src/test/java/com/baeldung/reports/CustomisedReports.java @@ -1,8 +1,5 @@ package com.baeldung.reports; -import java.util.List; -import java.util.Map; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.IReporter; @@ -11,6 +8,9 @@ import org.testng.ISuiteResult; import org.testng.ITestContext; import org.testng.xml.XmlSuite; +import java.util.List; +import java.util.Map; + public class CustomisedReports implements IReporter { private static final Logger LOGGER = LoggerFactory.getLogger("TEST_REPORT"); @@ -18,32 +18,32 @@ public class CustomisedReports implements IReporter { public void generateReport(List xmlSuites, List suites, String outputDirectory) { suites.stream() - .forEach(suite -> { - String suiteName = suite.getName(); - Map suiteResults = suite.getResults(); - suiteResults.values() - .stream() - .forEach(result -> { - ITestContext context - = ((ISuiteResult) result).getTestContext(); + .forEach(suite -> { + String suiteName = suite.getName(); + Map suiteResults = suite.getResults(); + suiteResults.values() + .stream() + .forEach(result -> { + ITestContext context + = ((ISuiteResult) result).getTestContext(); - LOGGER.info("Passed tests for suite '" - + suiteName + "' is:" - + context.getPassedTests() - .getAllResults() - .size()); - LOGGER.info("Failed tests for suite '" - + suiteName + "' is:" - + context.getFailedTests() - .getAllResults() - .size()); - LOGGER.info("Skipped tests for suite '" - + suiteName + "' is:" - + context.getSkippedTests() - .getAllResults() - .size()); + LOGGER.info("Passed tests for suite '" + + suiteName + "' is:" + + context.getPassedTests() + .getAllResults() + .size()); + LOGGER.info("Failed tests for suite '" + + suiteName + "' is:" + + context.getFailedTests() + .getAllResults() + .size()); + LOGGER.info("Skipped tests for suite '" + + suiteName + "' is:" + + context.getSkippedTests() + .getAllResults() + .size()); + }); }); - }); }