commit
b1063f8da9
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [A Guide to JGit](http://www.baeldung.com/jgit)
|
|
@ -0,0 +1,58 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.mabsisa</groupId>
|
||||
<artifactId>Twitter4J</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>Twitter4J</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.twitter4j</groupId>
|
||||
<artifactId>twitter4j-core</artifactId>
|
||||
<version>4.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.twitter4j</groupId>
|
||||
<artifactId>twitter4j-stream</artifactId>
|
||||
<version>4.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.19.1</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/ApplicationTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -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<String> getTimeLine() throws TwitterException {
|
||||
Twitter twitter = getTwitterinstance();
|
||||
List<Status> 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<String> searchtweets() throws TwitterException {
|
||||
Twitter twitter = getTwitterinstance();
|
||||
Query query = new Query("source:twitter4j baeldung");
|
||||
QueryResult result = twitter.search(query);
|
||||
List<Status> 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
oauth.consumerKey=//TODO
|
||||
oauth.consumerSecret=//TODO
|
||||
oauth.accessToken=//TODO
|
||||
oauth.accessTokenSecret=//TODO
|
|
@ -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<String> statuses = Application.getTimeLine();
|
||||
List<String> expectedStatuses = new ArrayList<String>();
|
||||
expectedStatuses.add(tweet);
|
||||
assertEquals(expectedStatuses, statuses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRecipientNameAndMessage_sendDirectMessage() throws TwitterException {
|
||||
String msg = Application.sendDirectMessage("YOUR_RECCIPIENT_ID", tweet);
|
||||
assertEquals(msg, tweet);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Dijkstra Algorithm in Java](http://www.baeldung.com/java-dijkstra)
|
||||
- [Introduction to Cobertura](http://www.baeldung.com/cobertura)
|
|
@ -41,4 +41,23 @@
|
|||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<configuration>
|
||||
<instrumentation>
|
||||
<ignores>
|
||||
<ignore>com/baeldung/algorithms/dijkstra/*</ignore>
|
||||
</ignores>
|
||||
<excludes>
|
||||
<exclude>com/baeldung/algorithms/dijkstra/*</exclude>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
### Relevant Articles:
|
||||
- [Intro to Apache BVal](http://www.baeldung.com/apache-bval)
|
|
@ -0,0 +1,36 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-commons</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<properties>
|
||||
<junit.version>4.12</junit.version>
|
||||
<compiler.version>3.6.0</compiler.version>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${compiler.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
## Apache Solrj Tutorials Project
|
||||
|
||||
### Relevant Articles
|
||||
- [Guide to Solr in Java with Apache Solrj](http://www.baeldung.com/apache-solrj)
|
|
@ -0,0 +1,50 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>apache-solrj</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>apache-solrj</name>
|
||||
|
||||
<properties>
|
||||
<junit.version>4.12</junit.version>
|
||||
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<version>6.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Working with Apache Thrift](http://www.baeldung.com/apache-thrift)
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Introduction to Apache Velocity](http://www.baeldung.com/apache-velocity)
|
25
aws/pom.xml
25
aws/pom.xml
|
@ -7,17 +7,36 @@
|
|||
<packaging>jar</packaging>
|
||||
<name>aws</name>
|
||||
|
||||
<properties>
|
||||
<commons-io.version>2.5</commons-io.version>
|
||||
<aws-lambda-java-events.version>1.3.0</aws-lambda-java-events.version>
|
||||
<aws-lambda-java-core.version>1.1.0</aws-lambda-java-core.version>
|
||||
<gson.version>2.8.0</gson.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-core</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>${aws-lambda-java-core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-events</artifactId>
|
||||
<version>${aws-lambda-java-events.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -26,7 +45,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
|
|
|
@ -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<PersonRequest, PersonResponse> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${ch.qos.logback.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
|
@ -76,9 +81,9 @@
|
|||
|
||||
<!-- logging -->
|
||||
<org.slf4j.version>1.7.21</org.slf4j.version>
|
||||
|
||||
<ch.qos.logback.version>1.2.1</ch.qos.logback.version>
|
||||
<!-- maven plugins -->
|
||||
<maven-compiler-plugin.version>3.6-jigsaw-SNAPSHOT</maven-compiler-plugin.version>
|
||||
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||
|
||||
<!-- testing -->
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<ProcessHandle> 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<ProcessHandle> children = ProcessHandle.current()
|
||||
.children();
|
||||
children.filter(ProcessHandle::isAlive)
|
||||
.forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info()
|
||||
.command()));
|
||||
Stream<ProcessHandle> 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<ProcessHandle> onProcessExit = processHandle.onExit();
|
||||
onProcessExit.get();
|
||||
assertEquals(false, processHandle.isAlive());
|
||||
onProcessExit.thenAccept(ph -> {
|
||||
log.info("PID: {} has stopped", ph.getPid());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
*.class
|
||||
|
||||
0.*
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
.resourceCache
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -165,6 +165,12 @@
|
|||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.javamoney</groupId>
|
||||
<artifactId>moneta</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.algorithms.annealing;
|
||||
package com.baeldung.algorithms.ga.annealing;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.algorithms.annealing;
|
||||
package com.baeldung.algorithms.ga.annealing;
|
||||
|
||||
public class SimulatedAnnealing {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.algorithms.annealing;
|
||||
package com.baeldung.algorithms.ga.annealing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Ant> 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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String> 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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, String> 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();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, String> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.list.listoflist;
|
||||
|
||||
public interface Stationery {
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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'
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
### Relevant Articles:
|
||||
- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap)
|
|
@ -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<ArrayList<? extends Stationery>> listOfLists = new ArrayList<ArrayList<? extends Stationery>>();
|
||||
private ArrayList<Pen> penList = new ArrayList<>();
|
||||
private ArrayList<Pencil> pencilList = new ArrayList<>();
|
||||
private ArrayList<Rubber> rubberList = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void init() {
|
||||
listOfLists.add(penList);
|
||||
listOfLists.add(pencilList);
|
||||
listOfLists.add(rubberList);
|
||||
|
||||
((ArrayList<Pen>) listOfLists.get(0)).add(new Pen("Pen 1"));
|
||||
((ArrayList<Pencil>) listOfLists.get(1)).add(new Pencil("Pencil 1"));
|
||||
((ArrayList<Rubber>) 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<Pencil>) 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<Pen> pens = new ArrayList<>();
|
||||
pens.add(new Pen("Pen 1"));
|
||||
pens.add(new Pen("Pen 2"));
|
||||
ArrayList<Pencil> pencils = new ArrayList<>();
|
||||
pencils.add(new Pencil("Pencil 1"));
|
||||
pencils.add(new Pencil("Pencil 2"));
|
||||
ArrayList<Rubber> rubbers = new ArrayList<>();
|
||||
rubbers.add(new Rubber("Rubber 1"));
|
||||
rubbers.add(new Rubber("Rubber 2"));
|
||||
|
||||
List<ArrayList<? extends Stationery>> list = new ArrayList<ArrayList<? extends Stationery>>();
|
||||
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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Concurrency with LMAX Disruptor – An Introduction](http://www.baeldung.com/lmax-disruptor-concurrency)
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Guide to EJB Set-up](http://www.baeldung.com/ejb-intro)
|
|
@ -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)
|
||||
|
|
|
@ -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<String> stringList = Lists.newArrayList();
|
||||
ArrayList<Integer> intList = Lists.newArrayList();
|
||||
|
||||
//when
|
||||
boolean result = stringList.getClass().isAssignableFrom(intList.getClass());
|
||||
|
||||
//then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTypeToken_whenResolveType_thenShouldResolveProperType() {
|
||||
//given
|
||||
TypeToken<List<String>> stringListToken = new TypeToken<List<String>>() {
|
||||
};
|
||||
TypeToken<List<Integer>> integerListToken = new TypeToken<List<Integer>>() {
|
||||
};
|
||||
TypeToken<List<? extends Number>> numberTypeToken = new TypeToken<List<? extends Number>>() {
|
||||
};
|
||||
|
||||
//then
|
||||
assertFalse(stringListToken.isSubtypeOf(integerListToken));
|
||||
assertFalse(numberTypeToken.isSubtypeOf(integerListToken));
|
||||
assertTrue(integerListToken.isSubtypeOf(numberTypeToken));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCustomClass_whenCaptureGeneric_thenReturnTypeAtRuntime() {
|
||||
//given
|
||||
ParametrizedClass<String> parametrizedClass = new ParametrizedClass<String>() {
|
||||
};
|
||||
|
||||
//then
|
||||
assertEquals(parametrizedClass.type, TypeToken.of(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenComplexType_whenGetTypeArgument_thenShouldReturnTypeAtRuntime() {
|
||||
//given
|
||||
TypeToken<Function<Integer, String>> funToken = new TypeToken<Function<Integer, String>>() {
|
||||
};
|
||||
|
||||
//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<Map<String, Integer>> mapToken = new TypeToken<Map<String, Integer>>() {
|
||||
};
|
||||
|
||||
//when
|
||||
TypeToken<?> entrySetToken = mapToken.resolveType(Map.class.getMethod("entrySet").getGenericReturnType());
|
||||
|
||||
//then
|
||||
assertEquals(entrySetToken, new TypeToken<Set<Map.Entry<String, Integer>>>() {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInvokable_whenCheckPublicMethod_shouldReturnTrue() throws NoSuchMethodException {
|
||||
//given
|
||||
Method method = CustomClass.class.getMethod("somePublicMethod");
|
||||
Invokable<CustomClass, ?> invokable = new TypeToken<CustomClass>() {
|
||||
}.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<CustomClass, ?> invokable = new TypeToken<CustomClass>() {
|
||||
}.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<List<Integer>, ?> invokable = new TypeToken<List<Integer>>() {
|
||||
}.method(getMethod);
|
||||
|
||||
//then
|
||||
assertEquals(TypeToken.of(Integer.class), invokable.getReturnType()); // Not Object.class!
|
||||
}
|
||||
|
||||
|
||||
abstract class ParametrizedClass<T> {
|
||||
TypeToken<T> type = new TypeToken<T>(getClass()) {
|
||||
};
|
||||
}
|
||||
|
||||
class CustomClass {
|
||||
public void somePublicMethod() {
|
||||
}
|
||||
|
||||
public final void notOverridablePublicMethod() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.examples.guice</groupId>
|
||||
<artifactId>guice-intro</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<guice.version>4.1.0</guice.version>
|
||||
</properties>
|
||||
<name>guice-intro</name>
|
||||
</project>
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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<String> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.examples.guice.marker;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Baeldung
|
||||
*/
|
||||
public interface Communicator {
|
||||
|
||||
public boolean sendMessage(String message);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hbase</artifactId>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.hbase</groupId>
|
||||
<artifactId>hbase-client</artifactId>
|
||||
<version>${hbase.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.hbase</groupId>
|
||||
<artifactId>hbase</artifactId>
|
||||
<version>${hbase.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<hbase.version>1.3.0</hbase.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
</properties>
|
||||
|
||||
|
||||
</project>
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <table>
|
||||
* <tr>
|
||||
* <tb>Row1</tb> <tb>Family1:Qualifier1</tb> <tb>Family1:Qualifier2</tb>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <tb>Row2</tb> <tb>Family1:Qualifier1</tb> <tb>Family2:Qualifier3</tb>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <tb>Row3</tb> <tb>Family1:Qualifier1</tb> <tb>Family2:Qualifier3</tb>
|
||||
* </tr>
|
||||
* </table>
|
||||
*/
|
||||
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<Filter> 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.");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
|
||||
<configuration>
|
||||
<property>
|
||||
<name>hbase.zookeeper.quorum</name>
|
||||
<value>localhost</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>hbase.zookeeper.property.clientPort</name>
|
||||
<value>2181</value>
|
||||
</property>
|
||||
</configuration>
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>jasypt</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasypt</groupId>
|
||||
<artifactId>jasypt</artifactId>
|
||||
<version>${jasypt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<jasypt.version>1.9.2</jasypt.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
</properties>
|
||||
|
||||
|
||||
</project>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb)
|
|
@ -0,0 +1,41 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>java-websocket</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>java-websocket Maven Webapp</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.websocket</groupId>
|
||||
<artifactId>javax.websocket-api</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<ChatEndpoint> chatEndpoints = new CopyOnWriteArraySet<>();
|
||||
private static HashMap<String, String> 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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Message> {
|
||||
@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
|
||||
}
|
||||
}
|
|
@ -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<Message> {
|
||||
@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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
|
||||
</beans>
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE web-app PUBLIC
|
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" >
|
||||
|
||||
<web-app>
|
||||
<display-name>Archetype Created Web Application</display-name>
|
||||
</web-app>
|
|
@ -0,0 +1,30 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Chat</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="text" id="username" placeholder="Username"/>
|
||||
<button type="button" onclick="connect();" >Connect</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<textarea readonly="true" rows="10" cols="80" id="log"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" size="51" id="msg" placeholder="Message"/>
|
||||
<button type="button" onclick="send();" >Send</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
<script src="websocket.js"></script>
|
||||
|
||||
</html>
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue