diff --git a/algorithms/src/main/java/com/baeldung/algorithms/BinarySearch.java b/algorithms/src/main/java/com/baeldung/algorithms/BinarySearch.java new file mode 100644 index 0000000000..be4a9e578a --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/BinarySearch.java @@ -0,0 +1,26 @@ +public class BinarySearch { + + public int runBinarySearch() { + int[] sortedArray = { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 }; + int key = 6; + + int low = 0; + int high = sortedArray.length - 1; + int index = Integer.MAX_VALUE; + + while (low <= high) { + + int mid = (low + high) / 2; + + if (sortedArray[mid] < key) { + low = mid + 1; + } else if (sortedArray[mid] > key) { + high = mid - 1; + } else if (sortedArray[mid] == key) { + index = mid; + break; + } + } + return index; + } +} diff --git a/algorithms/src/test/java/algorithms/BinarySearchTest.java b/algorithms/src/test/java/algorithms/BinarySearchTest.java new file mode 100644 index 0000000000..d53b074cc4 --- /dev/null +++ b/algorithms/src/test/java/algorithms/BinarySearchTest.java @@ -0,0 +1,14 @@ +import org.junit.Assert; +import org.junit.Test; + + +public class BinarySearchTest { + + @Test + public void givenASortedArrayOfIntegers_whenBinarySearchRunForANumber_thenGetIndexOfTheNumber() { + BinarySearch binSearch = new BinarySearch(); + int expectedIndexForSearchKey = 7; + Assert.assertEquals(expectedIndexForSearchKey, binSearch.runBinarySearch()); + } + +} diff --git a/apache-shiro/.gitignore b/apache-shiro/.gitignore new file mode 100644 index 0000000000..020cda4898 --- /dev/null +++ b/apache-shiro/.gitignore @@ -0,0 +1,4 @@ + +/.idea/ +/target/ +/apache-shiro.iml \ No newline at end of file diff --git a/apache-shiro/README.md b/apache-shiro/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apache-shiro/pom.xml b/apache-shiro/pom.xml new file mode 100644 index 0000000000..97ed872a26 --- /dev/null +++ b/apache-shiro/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + com.baeldung + apache-shiro + 1.0-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + 1.4.0 + 1.2.17 + 1.7.25 + + + + + org.apache.shiro + shiro-core + ${apache-shiro-core-version} + + + org.slf4j + jcl-over-slf4j + ${slf4j-version} + runtime + + + org.slf4j + slf4j-log4j12 + ${slf4j-version} + runtime + + + log4j + log4j + ${log4j-version} + runtime + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.2 + + 1.8 + 1.8 + + + + + + + \ No newline at end of file diff --git a/apache-shiro/src/main/java/com/baeldung/Main.java b/apache-shiro/src/main/java/com/baeldung/Main.java new file mode 100644 index 0000000000..5e341f251b --- /dev/null +++ b/apache-shiro/src/main/java/com/baeldung/Main.java @@ -0,0 +1,85 @@ +package com.baeldung; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.mgt.DefaultSecurityManager; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.realm.Realm; +import org.apache.shiro.realm.text.IniRealm; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Main { + + private static final transient Logger log = LoggerFactory.getLogger(Main.class); + + public static void main(String[] args) { + + Realm realm = new MyCustomRealm(); + SecurityManager securityManager = new DefaultSecurityManager(realm); + + SecurityUtils.setSecurityManager(securityManager); + Subject currentUser = SecurityUtils.getSubject(); + + if (!currentUser.isAuthenticated()) { + UsernamePasswordToken token + = new UsernamePasswordToken("user", "password"); + token.setRememberMe(true); + try { + currentUser.login(token); + } catch (UnknownAccountException uae) { + log.error("Username Not Found!", uae); + } catch (IncorrectCredentialsException ice) { + log.error("Invalid Credentials!", ice); + } catch (LockedAccountException lae) { + log.error("Your Account is Locked!", lae); + } catch (AuthenticationException ae) { + log.error("Unexpected Error!", ae); + } + } + + log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); + + if (currentUser.hasRole("admin")) { + log.info("Welcome Admin"); + } else if(currentUser.hasRole("editor")) { + log.info("Welcome, Editor!"); + } else if(currentUser.hasRole("author")) { + log.info("Welcome, Author"); + } else { + log.info("Welcome, Guest"); + } + + if(currentUser.isPermitted("articles:compose")) { + log.info("You can compose an article"); + } else { + log.info("You are not permitted to compose an article!"); + } + + if(currentUser.isPermitted("articles:save")) { + log.info("You can save articles"); + } else { + log.info("You can not save articles"); + } + + if(currentUser.isPermitted("articles:publish")) { + log.info("You can publish articles"); + } else { + log.info("You can not publish articles"); + } + + Session session = currentUser.getSession(); + session.setAttribute("key", "value"); + String value = (String) session.getAttribute("key"); + if (value.equals("value")) { + log.info("Retrieved the correct value! [" + value + "]"); + } + + currentUser.logout(); + + System.exit(0); + } + +} diff --git a/apache-shiro/src/main/java/com/baeldung/MyCustomRealm.java b/apache-shiro/src/main/java/com/baeldung/MyCustomRealm.java new file mode 100644 index 0000000000..8d792c76a5 --- /dev/null +++ b/apache-shiro/src/main/java/com/baeldung/MyCustomRealm.java @@ -0,0 +1,102 @@ +package com.baeldung; + +import org.apache.shiro.authc.*; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.jdbc.JdbcRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.*; + +public class MyCustomRealm extends JdbcRealm { + + private Map credentials = new HashMap<>(); + private Map> roles = new HashMap<>(); + private Map> perm = new HashMap<>(); + + { + credentials.put("user", "password"); + credentials.put("user2", "password2"); + credentials.put("user3", "password3"); + + roles.put("user", new HashSet<>(Arrays.asList("admin"))); + roles.put("user2", new HashSet<>(Arrays.asList("editor"))); + roles.put("user3", new HashSet<>(Arrays.asList("author"))); + + perm.put("admin", new HashSet<>(Arrays.asList("*"))); + perm.put("editor", new HashSet<>(Arrays.asList("articles:*"))); + perm.put("author", + new HashSet<>(Arrays.asList("articles:compose", + "articles:save"))); + + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) + throws AuthenticationException { + + UsernamePasswordToken uToken = (UsernamePasswordToken) token; + + if(uToken.getUsername() == null + || uToken.getUsername().isEmpty() + || !credentials.containsKey(uToken.getUsername()) + ) { + throw new UnknownAccountException("username not found!"); + } + + + return new SimpleAuthenticationInfo( + uToken.getUsername(), credentials.get(uToken.getUsername()), + getName()); + } + + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + Set roleNames = new HashSet<>(); + Set permissions = new HashSet<>(); + + principals.forEach(p -> { + try { + Set roles = getRoleNamesForUser(null, (String) p); + roleNames.addAll(roles); + permissions.addAll(getPermissions(null, null,roles)); + } catch (SQLException e) { + e.printStackTrace(); + } + }); + + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames); + info.setStringPermissions(permissions); + return info; + } + + @Override + protected Set getRoleNamesForUser(Connection conn, String username) throws SQLException { + if(!roles.containsKey(username)) { + throw new SQLException("username not found!"); + } + + return roles.get(username); + } + + @Override + protected Set getPermissions(Connection conn, String username, Collection roleNames) throws SQLException { + for (String role : roleNames) { + if (!perm.containsKey(role)) { + throw new SQLException("role not found!"); + } + } + + Set finalSet = new HashSet<>(); + for (String role : roleNames) { + finalSet.addAll(perm.get(role)); + } + + return finalSet; + } + +} diff --git a/apache-shiro/src/main/resources/log4j.properties b/apache-shiro/src/main/resources/log4j.properties new file mode 100644 index 0000000000..897bf08221 --- /dev/null +++ b/apache-shiro/src/main/resources/log4j.properties @@ -0,0 +1,12 @@ +log4j.rootLogger=INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n + +log4j.logger.org.apache=WARN + +log4j.logger.org.apache.shiro=INFO + +log4j.logger.org.apache.shiro.util.ThreadContext=WARN +log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN \ No newline at end of file diff --git a/apache-shiro/src/main/resources/shiro.ini b/apache-shiro/src/main/resources/shiro.ini new file mode 100644 index 0000000000..0bb7567d1e --- /dev/null +++ b/apache-shiro/src/main/resources/shiro.ini @@ -0,0 +1,9 @@ +[users] +user = password,admin +user2 = password2,editor +user3 = password3,author + +[roles] +admin = * +editor = articles:* +author = articles:compose,articles:save \ No newline at end of file diff --git a/asciidoctor/README.md b/asciidoctor/README.md index 164200d227..3c602b6abd 100644 --- a/asciidoctor/README.md +++ b/asciidoctor/README.md @@ -1,3 +1,4 @@ ### Relevant articles -- [Introduction to Asciidoctor](http://www.baeldung.com/introduction-to-asciidoctor) \ No newline at end of file +- [Introduction to Asciidoctor](http://www.baeldung.com/introduction-to-asciidoctor) +- [Generating a Book with Asciidoctor](http://www.baeldung.com/asciidoctor-book) diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java index 93abe4e185..93579019a1 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java +++ b/core-java-9/src/test/java/com/baeldung/java9/language/Java9ObjectsAPIUnitTest.java @@ -10,17 +10,27 @@ import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; public class Java9ObjectsAPIUnitTest { - + + private List aMethodReturningNullList(){ + return null; + } + @Test public void givenNullObject_whenRequireNonNullElse_thenElse(){ - assertThat(Objects.requireNonNullElse(null, Collections.EMPTY_LIST), - is(Collections.EMPTY_LIST)); + List aList = Objects.requireNonNullElse( + aMethodReturningNullList(), Collections.EMPTY_LIST); + assertThat(aList, is(Collections.EMPTY_LIST)); + } + + private List aMethodReturningNonNullList(){ + return List.of("item1", "item2"); } @Test public void givenObject_whenRequireNonNullElse_thenObject(){ - assertThat(Objects.requireNonNullElse(List.of("item1", "item2"), - Collections.EMPTY_LIST), is(List.of("item1", "item2"))); + List aList = Objects.requireNonNullElse( + aMethodReturningNonNullList(), Collections.EMPTY_LIST); + assertThat(aList, is(List.of("item1", "item2"))); } @Test(expected = NullPointerException.class) @@ -30,8 +40,8 @@ public class Java9ObjectsAPIUnitTest { @Test public void givenObject_whenRequireNonNullElseGet_thenObject(){ - assertThat(Objects.requireNonNullElseGet(null, List::of), - is(List.of())); + List aList = Objects.requireNonNullElseGet(null, List::of); + assertThat(aList, is(List.of())); } @Test diff --git a/core-java/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java b/core-java/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java new file mode 100644 index 0000000000..063c835481 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/volatilekeyword/SharedObject.java @@ -0,0 +1,13 @@ +package com.baeldung.concurrent.volatilekeyword; + + +public class SharedObject { + private volatile int count=0; + + void increamentCount(){ + count++; + } + public int getCount(){ + return count; + } +} diff --git a/core-java/src/main/java/com/baeldung/java/networking/README.md b/core-java/src/main/java/com/baeldung/networking/README.md similarity index 100% rename from core-java/src/main/java/com/baeldung/java/networking/README.md rename to core-java/src/main/java/com/baeldung/networking/README.md diff --git a/core-java/src/main/java/com/baeldung/java/networking/cookies/PersistentCookieStore.java b/core-java/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java similarity index 96% rename from core-java/src/main/java/com/baeldung/java/networking/cookies/PersistentCookieStore.java rename to core-java/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java index 0d66406ac2..5d30491cfe 100644 --- a/core-java/src/main/java/com/baeldung/java/networking/cookies/PersistentCookieStore.java +++ b/core-java/src/main/java/com/baeldung/networking/cookies/PersistentCookieStore.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.cookies; +package com.baeldung.networking.cookies; import java.net.*; import java.util.List; diff --git a/core-java/src/main/java/com/baeldung/java/networking/cookies/ProxyAcceptCookiePolicy.java b/core-java/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java similarity index 93% rename from core-java/src/main/java/com/baeldung/java/networking/cookies/ProxyAcceptCookiePolicy.java rename to core-java/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java index 6d6371bfe0..0b5f6d7714 100644 --- a/core-java/src/main/java/com/baeldung/java/networking/cookies/ProxyAcceptCookiePolicy.java +++ b/core-java/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.cookies; +package com.baeldung.networking.cookies; import java.net.*; diff --git a/core-java/src/main/java/com/baeldung/java/networking/udp/EchoClient.java b/core-java/src/main/java/com/baeldung/networking/udp/EchoClient.java similarity index 96% rename from core-java/src/main/java/com/baeldung/java/networking/udp/EchoClient.java rename to core-java/src/main/java/com/baeldung/networking/udp/EchoClient.java index 916442533b..35a083de26 100644 --- a/core-java/src/main/java/com/baeldung/java/networking/udp/EchoClient.java +++ b/core-java/src/main/java/com/baeldung/networking/udp/EchoClient.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.udp; +package com.baeldung.networking.udp; import java.io.IOException; import java.net.DatagramPacket; diff --git a/core-java/src/main/java/com/baeldung/java/networking/udp/EchoServer.java b/core-java/src/main/java/com/baeldung/networking/udp/EchoServer.java similarity index 96% rename from core-java/src/main/java/com/baeldung/java/networking/udp/EchoServer.java rename to core-java/src/main/java/com/baeldung/networking/udp/EchoServer.java index 900d330786..34f2971cc4 100644 --- a/core-java/src/main/java/com/baeldung/java/networking/udp/EchoServer.java +++ b/core-java/src/main/java/com/baeldung/networking/udp/EchoServer.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.udp; +package com.baeldung.networking.udp; import java.io.IOException; import java.net.DatagramPacket; diff --git a/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java b/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java new file mode 100644 index 0000000000..09794c2596 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingClient.java @@ -0,0 +1,85 @@ +package com.baeldung.networking.udp.broadcast; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.stream.Collectors; + +public class BroadcastingClient { + private DatagramSocket socket; + private InetAddress address; + private int expectedServerCount; + private byte[] buf; + + public BroadcastingClient(int expectedServerCount) throws Exception { + this.expectedServerCount = expectedServerCount; + this.address = InetAddress.getByName("255.255.255.255"); + } + + public int discoverServers(String msg) throws IOException { + initializeSocketForBroadcasting(); + copyMessageOnBuffer(msg); + + // When we want to broadcast not just to local network, call listAllBroadcastAddresses() and execute broadcastPacket for each value. + broadcastPacket(address); + + return receivePackets(); + } + + List listAllBroadcastAddresses() throws SocketException { + List broadcastList = new ArrayList<>(); + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface networkInterface = interfaces.nextElement(); + + if (networkInterface.isLoopback() || !networkInterface.isUp()) { + continue; + } + + broadcastList.addAll(networkInterface.getInterfaceAddresses() + .stream() + .filter(address -> address.getBroadcast() != null) + .map(address -> address.getBroadcast()) + .collect(Collectors.toList())); + } + return broadcastList; + } + + private void initializeSocketForBroadcasting() throws SocketException { + socket = new DatagramSocket(); + socket.setBroadcast(true); + } + + private void copyMessageOnBuffer(String msg) { + buf = msg.getBytes(); + } + + private void broadcastPacket(InetAddress address) throws IOException { + DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445); + socket.send(packet); + } + + private int receivePackets() throws IOException { + int serversDiscovered = 0; + while (serversDiscovered != expectedServerCount) { + receivePacket(); + serversDiscovered++; + } + return serversDiscovered; + } + + private void receivePacket() throws IOException { + DatagramPacket packet = new DatagramPacket(buf, buf.length); + socket.receive(packet); + } + + public void close() { + socket.close(); + } +} diff --git a/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java b/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java new file mode 100644 index 0000000000..b519f899bb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/udp/broadcast/BroadcastingEchoServer.java @@ -0,0 +1,44 @@ +package com.baeldung.networking.udp.broadcast; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; + +public class BroadcastingEchoServer extends Thread { + + protected DatagramSocket socket = null; + protected boolean running; + protected byte[] buf = new byte[256]; + + public BroadcastingEchoServer() throws IOException { + socket = new DatagramSocket(null); + socket.setReuseAddress(true); + socket.bind(new InetSocketAddress(4445)); + } + + public void run() { + running = true; + + while (running) { + try { + DatagramPacket packet = new DatagramPacket(buf, buf.length); + socket.receive(packet); + InetAddress address = packet.getAddress(); + int port = packet.getPort(); + packet = new DatagramPacket(buf, buf.length, address, port); + String received = new String(packet.getData(), 0, packet.getLength()); + if (received.equals("end")) { + running = false; + continue; + } + socket.send(packet); + } catch (IOException e) { + e.printStackTrace(); + running = false; + } + } + socket.close(); + } +} diff --git a/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java b/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java new file mode 100644 index 0000000000..9d63dd6386 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastEchoServer.java @@ -0,0 +1,41 @@ +package com.baeldung.networking.udp.multicast; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.MulticastSocket; + +public class MulticastEchoServer extends Thread { + + protected MulticastSocket socket = null; + protected byte[] buf = new byte[256]; + protected InetAddress group = null; + + public MulticastEchoServer() throws IOException { + socket = new MulticastSocket(4446); + socket.setReuseAddress(true); + group = InetAddress.getByName("230.0.0.0"); + socket.joinGroup(group); + } + + public void run() { + try { + while (true) { + DatagramPacket packet = new DatagramPacket(buf, buf.length); + socket.receive(packet); + InetAddress address = packet.getAddress(); + int port = packet.getPort(); + packet = new DatagramPacket(buf, buf.length, address, port); + String received = new String(packet.getData(), 0, packet.getLength()); + if (received.equals("end")) { + break; + } + socket.send(packet); + } + socket.leaveGroup(group); + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java b/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java new file mode 100644 index 0000000000..e89abc939d --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/udp/multicast/MulticastingClient.java @@ -0,0 +1,53 @@ +package com.baeldung.networking.udp.multicast; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; + +public class MulticastingClient { + private DatagramSocket socket; + private InetAddress group; + private int expectedServerCount; + private byte[] buf; + + public MulticastingClient(int expectedServerCount) throws Exception { + this.expectedServerCount = expectedServerCount; + this.socket = new DatagramSocket(); + this.group = InetAddress.getByName("230.0.0.0"); + } + + public int discoverServers(String msg) throws IOException { + copyMessageOnBuffer(msg); + multicastPacket(); + + return receivePackets(); + } + + private void copyMessageOnBuffer(String msg) { + buf = msg.getBytes(); + } + + private void multicastPacket() throws IOException { + DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 4446); + socket.send(packet); + } + + private int receivePackets() throws IOException { + int serversDiscovered = 0; + while (serversDiscovered != expectedServerCount) { + receivePacket(); + serversDiscovered++; + } + return serversDiscovered; + } + + private void receivePacket() throws IOException { + DatagramPacket packet = new DatagramPacket(buf, buf.length); + socket.receive(packet); + } + + public void close() { + socket.close(); + } +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java new file mode 100644 index 0000000000..8770cb4e90 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/volatilekeyword/SharedObjectManualTest.java @@ -0,0 +1,71 @@ +package com.baeldung.concurrent.volatilekeyword; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public class SharedObjectManualTest { + + private SharedObject sharedObject; + private int valueReadByThread2; + private int valueReadByThread3; + + @Before + public void setUp() { + sharedObject = new SharedObject(); + } + + @Test + public void whenOneThreadWrites_thenVolatileReadsFromMainMemory() throws InterruptedException { + Thread writer = new Thread(() -> sharedObject.increamentCount()); + writer.start(); + + + Thread readerOne = new Thread(() -> { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + valueReadByThread2 = sharedObject.getCount(); + }); + readerOne.start(); + + Thread readerTwo = new Thread(() -> { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + valueReadByThread3 = sharedObject.getCount(); + }); + readerTwo.start(); + + assertEquals(1, valueReadByThread2); + assertEquals(1, valueReadByThread3); + + } + + @Test + public void whenTwoThreadWrites_thenVolatileReadsFromMainMemory() throws InterruptedException { + Thread writerOne = new Thread(() -> sharedObject.increamentCount()); + writerOne.start(); + Thread.sleep(100); + + Thread writerTwo = new Thread(() -> sharedObject.increamentCount()); + writerTwo.start(); + Thread.sleep(100); + + Thread readerOne = new Thread(() -> valueReadByThread2 = sharedObject.getCount()); + readerOne.start(); + + Thread readerTwo = new Thread(() -> valueReadByThread3 = sharedObject.getCount()); + readerTwo.start(); + + assertEquals(2, valueReadByThread2); + assertEquals(2, valueReadByThread3); + + } +} diff --git a/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java b/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java new file mode 100644 index 0000000000..ed36951f73 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/javanetworking/uriurl/URIvsURLUnitTest.java @@ -0,0 +1,78 @@ +package com.baeldung.javanetworking.uriurl; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import org.apache.commons.io.IOUtils; +import static org.junit.Assert.*; +import org.junit.Test; + +public class URIvsURLUnitTest { + + @Test + public void whenCreatingURIs_thenSameInfo() throws URISyntaxException { + URI firstURI = new URI("somescheme://theuser:thepassword@someauthority:80/some/path?thequery#somefragment"); + URI secondURI = new URI("somescheme", "theuser:thepassword", "someuthority", 80, "/some/path", "thequery", "somefragment"); + + assertEquals(firstURI.getScheme(), secondURI.getScheme()); + assertEquals(firstURI.getPath(), secondURI.getPath()); + } + + @Test + public void whenCreatingURLs_thenSameInfo() throws MalformedURLException { + URL firstURL = new URL("http://theuser:thepassword@somehost:80/path/to/file?thequery#somefragment"); + URL secondURL = new URL("http", "somehost", 80, "/path/to/file"); + + assertEquals(firstURL.getHost(), secondURL.getHost()); + assertEquals(firstURL.getPath(), secondURL.getPath()); + } + + @Test + public void whenCreatingURI_thenCorrect() { + URI uri = URI.create("urn:isbn:1234567890"); + + assertNotNull(uri); + } + + @Test(expected = MalformedURLException.class) + public void whenCreatingURLs_thenException() throws MalformedURLException { + URL theURL = new URL("otherprotocol://somehost/path/to/file"); + + assertNotNull(theURL); + } + + @Test + public void givenObjects_whenConverting_thenCorrect() throws MalformedURLException, URISyntaxException { + String aURIString = "http://somehost:80/path?thequery"; + URI uri = new URI(aURIString); + URL url = new URL(aURIString); + + URL toURL = uri.toURL(); + URI toURI = url.toURI(); + + assertNotNull(url); + assertNotNull(uri); + assertEquals(toURL.toString(), toURI.toString()); + } + + @Test(expected = MalformedURLException.class) + public void givenURI_whenConvertingToURL_thenException() throws MalformedURLException, URISyntaxException { + URI uri = new URI("somescheme://someauthority/path?thequery"); + + URL url = uri.toURL(); + + assertNotNull(url); + } + + @Test + public void givenURL_whenGettingContents_thenCorrect() throws MalformedURLException, IOException { + URL url = new URL("http://courses.baeldung.com"); + + String contents = IOUtils.toString(url.openStream()); + + assertTrue(contents.contains("")); + } + +} diff --git a/core-java/src/test/java/com/baeldung/java/networking/udp/UDPIntegrationTest.java b/core-java/src/test/java/com/baeldung/networking/udp/UDPIntegrationTest.java similarity index 95% rename from core-java/src/test/java/com/baeldung/java/networking/udp/UDPIntegrationTest.java rename to core-java/src/test/java/com/baeldung/networking/udp/UDPIntegrationTest.java index aff851ae4b..968c01d24e 100644 --- a/core-java/src/test/java/com/baeldung/java/networking/udp/UDPIntegrationTest.java +++ b/core-java/src/test/java/com/baeldung/networking/udp/UDPIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.java.networking.udp; +package com.baeldung.networking.udp; import org.junit.After; import org.junit.Before; diff --git a/core-java/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastIntegrationTest.java b/core-java/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastIntegrationTest.java new file mode 100644 index 0000000000..c4f1e1f42c --- /dev/null +++ b/core-java/src/test/java/com/baeldung/networking/udp/broadcast/BroadcastIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.networking.udp.broadcast; + +import org.junit.After; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class BroadcastIntegrationTest { + private BroadcastingClient client; + + @Test + public void whenBroadcasting_thenDiscoverExpectedServers() throws Exception { + int expectedServers = 4; + initializeForExpectedServers(expectedServers); + + int serversDiscovered = client.discoverServers("hello server"); + assertEquals(expectedServers, serversDiscovered); + } + + private void initializeForExpectedServers(int expectedServers) throws Exception { + for (int i = 0; i < expectedServers; i++) { + new BroadcastingEchoServer().start(); + } + + client = new BroadcastingClient(expectedServers); + } + + @After + public void tearDown() throws IOException { + stopEchoServer(); + client.close(); + } + + private void stopEchoServer() throws IOException { + client.discoverServers("end"); + } +} diff --git a/core-java/src/test/java/com/baeldung/networking/udp/multicast/MulticastIntegrationTest.java b/core-java/src/test/java/com/baeldung/networking/udp/multicast/MulticastIntegrationTest.java new file mode 100644 index 0000000000..404f6c4e85 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/networking/udp/multicast/MulticastIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.networking.udp.multicast; + +import org.junit.After; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class MulticastIntegrationTest { + private MulticastingClient client; + + @Test + public void whenBroadcasting_thenDiscoverExpectedServers() throws Exception { + int expectedServers = 4; + initializeForExpectedServers(expectedServers); + + int serversDiscovered = client.discoverServers("hello server"); + assertEquals(expectedServers, serversDiscovered); + } + + private void initializeForExpectedServers(int expectedServers) throws Exception { + for (int i = 0; i < expectedServers; i++) { + new MulticastEchoServer().start(); + } + + client = new MulticastingClient(expectedServers); + } + + @After + public void tearDown() throws IOException { + stopEchoServer(); + client.close(); + } + + private void stopEchoServer() throws IOException { + client.discoverServers("end"); + } +} diff --git a/easy-rules/pom.xml b/easy-rules/pom.xml new file mode 100644 index 0000000000..b74b16f34c --- /dev/null +++ b/easy-rules/pom.xml @@ -0,0 +1,15 @@ + + 4.0.0 + com.baeldung.easyrules + easy-rules + 1.0.0-SNAPSHOT + + + + org.jeasy + easy-rules-core + 3.0.0 + + + \ No newline at end of file diff --git a/easy-rules/src/main/java/com/baeldung/easyrules/HelloWorldRule.java b/easy-rules/src/main/java/com/baeldung/easyrules/HelloWorldRule.java new file mode 100644 index 0000000000..5448eabf2a --- /dev/null +++ b/easy-rules/src/main/java/com/baeldung/easyrules/HelloWorldRule.java @@ -0,0 +1,20 @@ +package com.baeldung.easyrules; + +import org.jeasy.rules.annotation.Action; +import org.jeasy.rules.annotation.Condition; +import org.jeasy.rules.annotation.Rule; + +@Rule(name = "Hello World rule", description = "Always say hello world") +public class HelloWorldRule { + + @Condition + public boolean when() { + return true; + } + + @Action + public void then() throws Exception { + System.out.println("hello world"); + } + +} diff --git a/easy-rules/src/main/java/com/baeldung/easyrules/Launcher.java b/easy-rules/src/main/java/com/baeldung/easyrules/Launcher.java new file mode 100644 index 0000000000..427e3eace0 --- /dev/null +++ b/easy-rules/src/main/java/com/baeldung/easyrules/Launcher.java @@ -0,0 +1,21 @@ +package com.baeldung.easyrules; + +import org.jeasy.rules.api.Facts; +import org.jeasy.rules.api.Rules; +import org.jeasy.rules.api.RulesEngine; +import org.jeasy.rules.core.DefaultRulesEngine; + +public class Launcher { + public static void main(String... args) { + // create facts + Facts facts = new Facts(); + + // create rules + Rules rules = new Rules(); + rules.register(new HelloWorldRule()); + + // create a rules engine and fire rules on known facts + RulesEngine rulesEngine = new DefaultRulesEngine(); + rulesEngine.fire(rules, facts); + } +} diff --git a/ejb/ejb-client/src/main/resources/jboss-ejb-client.properties b/ejb/ejb-client/src/main/resources/jboss-ejb-client.properties index a01a675e44..67533b7825 100755 --- a/ejb/ejb-client/src/main/resources/jboss-ejb-client.properties +++ b/ejb/ejb-client/src/main/resources/jboss-ejb-client.properties @@ -1,8 +1,8 @@ +endpoint.name=client-endpoint +remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default remote.connection.default.host=127.0.0.1 remote.connection.default.port=8080 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false -remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false -remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=${host.auth:JBOSS-LOCAL-USER} -remote.connection.default.username=testUser -remote.connection.default.password=admin1234! +remote.connection.default.username=myusername +remote.connection.default.password=mypassword \ No newline at end of file diff --git a/ejb/ejbclient/src/main/java/com/baeldung/ejbclient/application/TextApplication.java b/ejb/ejbclient/src/main/java/com/baeldung/ejbclient/application/TextApplication.java new file mode 100644 index 0000000000..b65c21100d --- /dev/null +++ b/ejb/ejbclient/src/main/java/com/baeldung/ejbclient/application/TextApplication.java @@ -0,0 +1,42 @@ +package com.baeldung.ejbclient.application; + +import com.baeldung.ejbmodule.TextProcessorBean; +import com.baeldung.ejbmodule.TextProcessorRemote; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import java.util.Properties; + +public class TextApplication { + + public static void main(String[] args) throws NamingException { + TextProcessorRemote textProcessor = EJBFactory.createTextProcessorBeanFromJNDI("ejb:"); + System.out.print(textProcessor.processText("sample text")); + } + + private static class EJBFactory { + + private static TextProcessorRemote createTextProcessorBeanFromJNDI(String namespace) throws NamingException { + return lookupTextProcessorBean(namespace); + } + + private static TextProcessorRemote lookupTextProcessorBean(String namespace) throws NamingException { + Context ctx = createInitialContext(); + final String appName = ""; + final String moduleName = "EJBModule"; + final String distinctName = ""; + final String beanName = TextProcessorBean.class.getSimpleName(); + final String viewClassName = TextProcessorRemote.class.getName(); + return (TextProcessorRemote) ctx.lookup(namespace + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName); + } + + private static Context createInitialContext() throws NamingException { + Properties jndiProperties = new Properties(); + jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory"); + jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); + jndiProperties.put(Context.PROVIDER_URL, "http-remoting://localhost:8080"); + jndiProperties.put("jboss.naming.client.ejb.context", true); + return new InitialContext(jndiProperties); + } + } +} diff --git a/ejb/ejbclient/src/main/resources/jboss-ejb-client.properties b/ejb/ejbclient/src/main/resources/jboss-ejb-client.properties new file mode 100644 index 0000000000..67533b7825 --- /dev/null +++ b/ejb/ejbclient/src/main/resources/jboss-ejb-client.properties @@ -0,0 +1,8 @@ +endpoint.name=client-endpoint +remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false +remote.connections=default +remote.connection.default.host=127.0.0.1 +remote.connection.default.port=8080 +remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false +remote.connection.default.username=myusername +remote.connection.default.password=mypassword \ No newline at end of file diff --git a/ejb/ejbclient/src/test/java/com/baeldung/ejbclient/application/TextApplicationTest.java b/ejb/ejbclient/src/test/java/com/baeldung/ejbclient/application/TextApplicationTest.java new file mode 100644 index 0000000000..947c72d0b0 --- /dev/null +++ b/ejb/ejbclient/src/test/java/com/baeldung/ejbclient/application/TextApplicationTest.java @@ -0,0 +1,31 @@ +package com.baeldung.ejbclient.application; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import javax.naming.NamingException; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import static org.junit.Assert.*; + +public class TextApplicationTest { + + private static ByteArrayOutputStream outContent; + + @BeforeClass + public static void setUpPrintStreamInstance() { + outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + } + + @AfterClass + public static void tearDownByteArrayOutputStream() { + outContent = null; + } + + @Test + public void givenInputString_whenCompareTtoStringPrintedToConsole_thenSuccessful() throws NamingException { + TextApplication.main(new String[]{}); + assertEquals("SAMPLE TEXT", outContent.toString()); + } +} \ No newline at end of file diff --git a/ejb/ejbmodule/src/main/java/com/baeldung/ejbmodule/TextProcessorBean.java b/ejb/ejbmodule/src/main/java/com/baeldung/ejbmodule/TextProcessorBean.java new file mode 100644 index 0000000000..dc0db5fc53 --- /dev/null +++ b/ejb/ejbmodule/src/main/java/com/baeldung/ejbmodule/TextProcessorBean.java @@ -0,0 +1,10 @@ +package com.baeldung.ejbmodule; + +import javax.ejb.Stateless; + +@Stateless +public class TextProcessorBean implements TextProcessorRemote { + public String processText(String text) { + return text.toUpperCase(); + } +} diff --git a/ejb/ejbmodule/src/main/java/com/baeldung/ejbmodule/TextProcessorRemote.java b/ejb/ejbmodule/src/main/java/com/baeldung/ejbmodule/TextProcessorRemote.java new file mode 100644 index 0000000000..680d8f4e10 --- /dev/null +++ b/ejb/ejbmodule/src/main/java/com/baeldung/ejbmodule/TextProcessorRemote.java @@ -0,0 +1,9 @@ +package com.baeldung.ejbmodule; + +import javax.ejb.Remote; + +@Remote +public interface TextProcessorRemote { + + String processText(String text); +} \ No newline at end of file diff --git a/ejb/ejbmodule/src/test/java/com/baeldung/ejbmodule/TextProcessorBeanTest.java b/ejb/ejbmodule/src/test/java/com/baeldung/ejbmodule/TextProcessorBeanTest.java new file mode 100644 index 0000000000..d8693420d4 --- /dev/null +++ b/ejb/ejbmodule/src/test/java/com/baeldung/ejbmodule/TextProcessorBeanTest.java @@ -0,0 +1,12 @@ +package com.baeldung.ejbmodule; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class TextProcessorBeanTest { + @Test + public void givenInputString_whenComparedToStringParsedByBean_thenSuccessful() { + TextProcessorBean textProcessor = new TextProcessorBean(); + assertEquals("TEST", textProcessor.processText("test")); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java index 45d957b90b..035ff8ca9c 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java @@ -1,19 +1,23 @@ package com.baeldung.jackson.test; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import java.io.IOException; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.Test; import com.baeldung.jackson.deserialization.ItemDeserializer; import com.baeldung.jackson.dtos.Item; import com.baeldung.jackson.dtos.ItemWithSerializer; import com.baeldung.jackson.dtos.MyDto; import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreUnknown; -import org.junit.Test; - import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; @@ -21,6 +25,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -165,4 +170,35 @@ public class JacksonDeserializationUnitTest { assertThat(readValue, notNullValue()); } + @Test + public void whenDeserialisingZonedDateTimeWithDefaults_thenTimeZoneIsNotPreserved() throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.findAndRegisterModules(); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + // construct a new instance of ZonedDateTime + ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Berlin")); + String converted = objectMapper.writeValueAsString(now); + // restore an instance of ZonedDateTime from String + ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class); + System.out.println("serialized: " + now); + System.out.println("restored: " + restored); + assertThat(now, is(not(restored))); + } + + @Test + public void whenDeserialisingZonedDateTimeWithFeaturesDisabled_thenTimeZoneIsPreserved() throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.findAndRegisterModules(); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + // construct a new instance of ZonedDateTime + ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Berlin")); + String converted = objectMapper.writeValueAsString(now); + // restore an instance of ZonedDateTime from String + ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class); + System.out.println("serialized: " + now); + System.out.println("restored: " + restored); + assertThat(now, is(restored)); + } + } diff --git a/kotlin/README.md b/kotlin/README.md index 6b3fb93dcc..91933e94dc 100644 --- a/kotlin/README.md +++ b/kotlin/README.md @@ -7,3 +7,10 @@ - [Difference Between “==” and “===” in Kotlin](http://www.baeldung.com/kotlin-equality-operators) - [Generics in Kotlin](http://www.baeldung.com/kotlin-generics) - [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines) +- [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations) +- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito) +- [Lazy Initialization in Kotlin](http://www.baeldung.com/kotlin-lazy-initialization) +- [Overview of Kotlin Collections API](http://www.baeldung.com/kotlin-collections-api) +- [Converting a List to Map in Kotlin](http://www.baeldung.com/kotlin-list-to-map) +- [Data Classes in Kotlin](http://www.baeldung.com/kotlin-data-classes) + diff --git a/libraries/README.md b/libraries/README.md index 88075af390..ed6d214c7a 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -23,6 +23,7 @@ - [Serenity BDD with Spring and JBehave](http://www.baeldung.com/serenity-spring-jbehave) - [Locality-Sensitive Hashing in Java Using Java-LSH](http://www.baeldung.com/locality-sensitive-hashing) - [Apache Commons Collections OrderedMap](http://www.baeldung.com/apache-commons-ordered-map) +- [Introduction to Apache Commons Text](http://www.baeldung.com/java-apache-commons-text) - [A Guide to Apache Commons DbUtils](http://www.baeldung.com/apache-commons-dbutils) - [Introduction to Awaitility](http://www.baeldung.com/awaitlity-testing) - [Guide to the HyperLogLog Algorithm](http://www.baeldung.com/java-hyperloglog) diff --git a/libraries/pom.xml b/libraries/pom.xml index 490302ca29..ddfd75da82 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -186,11 +186,11 @@ rome ${rome.version} - - io.specto - hoverfly-java - 0.8.0 - + + io.specto + hoverfly-java + 0.8.0 + org.apache.httpcomponents httpclient @@ -212,6 +212,11 @@ commons-chain ${commons-chain.version} + + org.apache.commons + commons-csv + ${commons-csv.version} + commons-dbutils commons-dbutils @@ -380,7 +385,7 @@ one.util streamex - 0.6.5 + ${streamex.version} org.jooq @@ -467,11 +472,16 @@ noexception 1.1.0 - + org.eclipse.collections eclipse-collections ${eclipse-collections.version} + + io.vavr + vavr + ${vavr.version} + 0.7.0 @@ -480,6 +490,7 @@ 1.1 1.9.3 1.2 + 1.4 1.9.2 1.2 3.21.0-GA @@ -513,6 +524,8 @@ 1.7.1 2.1.2 1.0 - 8.2.0 + 8.2.0 + 0.6.5 + 0.9.0 diff --git a/libraries/src/main/java/com/baeldung/distinct/DistinctWithJavaFunction.java b/libraries/src/main/java/com/baeldung/distinct/DistinctWithJavaFunction.java new file mode 100644 index 0000000000..0d08c94b47 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/distinct/DistinctWithJavaFunction.java @@ -0,0 +1,15 @@ +package com.baeldung.distinct; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; + +public class DistinctWithJavaFunction { + + public static Predicate distinctByKey(Function keyExtractor) { + Map seen = new ConcurrentHashMap<>(); + return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; + } + +} diff --git a/libraries/src/main/java/com/baeldung/distinct/Person.java b/libraries/src/main/java/com/baeldung/distinct/Person.java new file mode 100644 index 0000000000..8a2a5f7a45 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/distinct/Person.java @@ -0,0 +1,65 @@ +package com.baeldung.distinct; + +public class Person { + int age; + String name; + String email; + + public Person(int age, String name, String email) { + super(); + this.age = age; + this.name = name; + this.email = email; + } + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Person [age="); + builder.append(age); + builder.append(", name="); + builder.append(name); + builder.append(", email="); + builder.append(email); + builder.append("]"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((email == null) ? 0 : email.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Person other = (Person) obj; + if (email == null) { + if (other.email != null) + return false; + } else if (!email.equals(other.email)) + return false; + return true; + } + +} diff --git a/libraries/src/main/java/com/baeldung/eclipsecollections/Student.java b/libraries/src/main/java/com/baeldung/eclipsecollections/Student.java index 2c634a28d9..cf6c06cec0 100644 --- a/libraries/src/main/java/com/baeldung/eclipsecollections/Student.java +++ b/libraries/src/main/java/com/baeldung/eclipsecollections/Student.java @@ -1,15 +1,25 @@ package com.baeldung.eclipsecollections; +import java.util.List; + public class Student { private String firstName; private String lastName; + private List addresses; public Student(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } + public Student(String firstName, String lastName, List addresses) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.addresses = addresses; + } + public String getFirstName() { return this.firstName; } @@ -17,4 +27,20 @@ public class Student { public String getLastName() { return this.lastName; } + + public List getAddresses() { + return addresses; + } + + public void setAddresses(List addresses) { + this.addresses = addresses; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } } \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/commons/collections4/BagTests.java b/libraries/src/test/java/com/baeldung/commons/collections4/BagTests.java new file mode 100644 index 0000000000..1270c50008 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/collections4/BagTests.java @@ -0,0 +1,85 @@ +package com.baeldung.commons.collections4; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.collections4.Bag; +import org.apache.commons.collections4.bag.CollectionBag; +import org.apache.commons.collections4.bag.HashBag; +import org.apache.commons.collections4.bag.TreeBag; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class BagTests { + + Bag baseBag; + TreeBag treeBag; + + @Before + public void before() { + baseBag = new HashBag(); + treeBag = new TreeBag(); + treeBag = new TreeBag(); + } + + @Test + public void whenAdd_thenRemoveFromBaseBag_thenContainsCorrect() { + baseBag.add("apple", 2); + baseBag.add("lemon", 6); + baseBag.add("lime"); + + baseBag.remove("lemon"); + Assert.assertEquals(3, baseBag.size()); + Assert.assertFalse(baseBag.contains("lemon")); + + Assert.assertTrue(baseBag.uniqueSet().contains("apple")); + Assert.assertFalse(baseBag.uniqueSet().contains("lemon")); + Assert.assertTrue(baseBag.uniqueSet().contains("lime")); + + List containList = new ArrayList(); + containList.add("apple"); + containList.add("lemon"); + containList.add("lime"); + Assert.assertFalse(baseBag.containsAll(containList)); + } + + @Test + public void whenAdd_thenRemoveFromBaseCollectionBag_thenContainsCorrect() { + baseBag.add("apple", 2); + baseBag.add("lemon", 6); + baseBag.add("lime"); + + CollectionBag baseCollectionBag = new CollectionBag( + baseBag); + + baseCollectionBag.remove("lemon"); + Assert.assertEquals(8, baseCollectionBag.size()); + Assert.assertTrue(baseCollectionBag.contains("lemon")); + + Assert.assertTrue(baseBag.uniqueSet().contains("apple")); + Assert.assertTrue(baseBag.uniqueSet().contains("lemon")); + Assert.assertTrue(baseBag.uniqueSet().contains("lime")); + + List containList = new ArrayList(); + containList.add("apple"); + containList.add("lemon"); + containList.add("lime"); + Assert.assertTrue(baseBag.containsAll(containList)); + } + + @Test + public void whenAddtoTreeBag_thenRemove_thenContainsCorrect() { + treeBag.add("banana", 8); + treeBag.add("apple", 2); + treeBag.add("lime"); + + Assert.assertEquals(11, treeBag.size()); + Assert.assertEquals("apple", treeBag.first()); + Assert.assertEquals("lime", treeBag.last()); + + treeBag.remove("apple"); + Assert.assertEquals(9, treeBag.size()); + Assert.assertEquals("banana", treeBag.first()); + } +} diff --git a/libraries/src/test/java/com/baeldung/commons/csv/CSVReaderWriterTest.java b/libraries/src/test/java/com/baeldung/commons/csv/CSVReaderWriterTest.java new file mode 100644 index 0000000000..6f47b89396 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/commons/csv/CSVReaderWriterTest.java @@ -0,0 +1,60 @@ +package com.baeldung.commons.csv; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringWriter; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +public class CSVReaderWriterTest { + + public static final Map AUTHOR_BOOK_MAP = Collections.unmodifiableMap(new LinkedHashMap() { + { + put("Dan Simmons", "Hyperion"); + put("Douglas Adams", "The Hitchhiker's Guide to the Galaxy"); + } + }); + public static final String[] HEADERS = { "author", "title" }; + public static final String EXPECTED_FILESTREAM = "author,title\r\n" + "Dan Simmons,Hyperion\r\n" + "Douglas Adams,The Hitchhiker's Guide to the Galaxy"; + + @Test + public void givenCSVFile_whenRead_thenContentsAsExpected() throws IOException { + Reader in = new FileReader("src/test/resources/book.csv"); + Iterable records = CSVFormat.DEFAULT + .withHeader(HEADERS) + .withFirstRecordAsHeader() + .parse(in); + for (CSVRecord record : records) { + String author = record.get("author"); + String title = record.get("title"); + assertEquals(AUTHOR_BOOK_MAP.get(author), title); + } + } + + @Test + public void givenAuthorBookMap_whenWrittenToStream_thenOutputStreamAsExpected() throws IOException { + StringWriter sw = new StringWriter(); + try (final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withHeader(HEADERS))) { + AUTHOR_BOOK_MAP.forEach((author, title) -> { + try { + printer.printRecord(author, title); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + assertEquals(EXPECTED_FILESTREAM, sw + .toString() + .trim()); + } + +} diff --git a/libraries/src/test/java/com/baeldung/distinct/DistinctWithEclipseCollectionsUnitTest.java b/libraries/src/test/java/com/baeldung/distinct/DistinctWithEclipseCollectionsUnitTest.java new file mode 100644 index 0000000000..dffde3917c --- /dev/null +++ b/libraries/src/test/java/com/baeldung/distinct/DistinctWithEclipseCollectionsUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.distinct; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.eclipse.collections.impl.block.factory.HashingStrategies; +import org.eclipse.collections.impl.utility.ListIterate; +import org.junit.Before; +import org.junit.Test; + +public class DistinctWithEclipseCollectionsUnitTest { + List personList; + + @Before + public void init() { + personList = PersonDataGenerator.getPersonListWithFakeValues(); + } + + @Test + public void whenFilterListByName_thenSizeShouldBe4() { + List personListFiltered = ListIterate.distinct(personList, HashingStrategies.fromFunction(Person::getName)); + assertTrue(personListFiltered.size() == 4); + } + + @Test + public void whenFilterListByAge_thenSizeShouldBe2() { + List personListFiltered = ListIterate.distinct(personList, HashingStrategies.fromIntFunction(Person::getAge)); + assertTrue(personListFiltered.size() == 2); + } + +} diff --git a/libraries/src/test/java/com/baeldung/distinct/DistinctWithJavaFunctionUnitTest.java b/libraries/src/test/java/com/baeldung/distinct/DistinctWithJavaFunctionUnitTest.java new file mode 100644 index 0000000000..68775fac66 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/distinct/DistinctWithJavaFunctionUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.distinct; + +import static org.junit.Assert.assertTrue; +import static com.baeldung.distinct.DistinctWithJavaFunction.distinctByKey; + +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.Before; +import org.junit.Test; + +public class DistinctWithJavaFunctionUnitTest { + List personList; + + @Before + public void init() { + personList = PersonDataGenerator.getPersonListWithFakeValues(); + } + + @Test + public void whenFilterListByName_thenSizeShouldBe4() { + List personListFiltered = personList.stream() + .filter(distinctByKey(p -> p.getName())) + .collect(Collectors.toList()); + assertTrue(personListFiltered.size() == 4); + } + + @Test + public void whenFilterListByAge_thenSizeShouldBe2() { + List personListFiltered = personList.stream() + .filter(distinctByKey(p -> p.getAge())) + .collect(Collectors.toList()); + assertTrue(personListFiltered.size() == 2); + } + + @Test + public void whenFilterListWithDefaultDistinct_thenSizeShouldBe5() { + List personListFiltered = personList.stream() + .distinct() + .collect(Collectors.toList()); + assertTrue(personListFiltered.size() == 5); + } + +} diff --git a/libraries/src/test/java/com/baeldung/distinct/DistinctWithStreamexUnitTest.java b/libraries/src/test/java/com/baeldung/distinct/DistinctWithStreamexUnitTest.java new file mode 100644 index 0000000000..f50c76a486 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/distinct/DistinctWithStreamexUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.distinct; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import one.util.streamex.StreamEx; + +public class DistinctWithStreamexUnitTest { + List personList; + + @Before + public void init() { + personList = PersonDataGenerator.getPersonListWithFakeValues(); + } + + @Test + public void whenFilterListByName_thenSizeShouldBe4() { + List personListFiltered = StreamEx.of(personList) + .distinct(Person::getName) + .toList(); + assertTrue(personListFiltered.size() == 4); + } + + @Test + public void whenFilterListByAge_thenSizeShouldBe2() { + List personListFiltered = StreamEx.of(personList) + .distinct(Person::getAge) + .toList(); + assertTrue(personListFiltered.size() == 2); + } + +} diff --git a/libraries/src/test/java/com/baeldung/distinct/DistinctWithVavrUnitTest.java b/libraries/src/test/java/com/baeldung/distinct/DistinctWithVavrUnitTest.java new file mode 100644 index 0000000000..b4025cd313 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/distinct/DistinctWithVavrUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.distinct; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class DistinctWithVavrUnitTest { + List personList; + + @Before + public void init() { + personList = PersonDataGenerator.getPersonListWithFakeValues(); + } + + @Test + public void whenFilterListByName_thenSizeShouldBe4() { + List personListFiltered = io.vavr.collection.List.ofAll(personList) + .distinctBy(Person::getName) + .toJavaList(); + assertTrue(personListFiltered.size() == 4); + } + + @Test + public void whenFilterListByAge_thenSizeShouldBe2() { + List personListFiltered = io.vavr.collection.List.ofAll(personList) + .distinctBy(Person::getAge) + .toJavaList(); + assertTrue(personListFiltered.size() == 2); + } + +} diff --git a/libraries/src/test/java/com/baeldung/distinct/PersonDataGenerator.java b/libraries/src/test/java/com/baeldung/distinct/PersonDataGenerator.java new file mode 100644 index 0000000000..51590005ac --- /dev/null +++ b/libraries/src/test/java/com/baeldung/distinct/PersonDataGenerator.java @@ -0,0 +1,19 @@ +package com.baeldung.distinct; + +import java.util.Arrays; +import java.util.List; + +public class PersonDataGenerator { + + public static List getPersonListWithFakeValues() { + // @formatter:off + return Arrays.asList( + new Person(20, "Jhon", "jhon@test.com"), + new Person(20, "Jhon", "jhon1@test.com"), + new Person(20, "Jhon", "jhon2@test.com"), + new Person(21, "Tom", "Tom@test.com"), + new Person(21, "Mark", "Mark@test.com"), + new Person(20, "Julia", "jhon@test.com")); + // @formatter:on + } +} diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/AllSatisfyPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/AllSatisfyPatternTest.java index 1ea10317c7..ee369fc75b 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/AllSatisfyPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/AllSatisfyPatternTest.java @@ -14,15 +14,7 @@ public class AllSatisfyPatternTest { @Before public void getList() { - this.list = new FastList<>(); - list.add(1); - list.add(8); - list.add(5); - list.add(41); - list.add(31); - list.add(17); - list.add(23); - list.add(38); + this.list = FastList.newListWith(1, 8, 5, 41, 31, 17, 23, 38); } @Test diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/AnySatisfyPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/AnySatisfyPatternTest.java index 58f8ad40af..a3314ebee6 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/AnySatisfyPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/AnySatisfyPatternTest.java @@ -14,15 +14,7 @@ public class AnySatisfyPatternTest { @Before public void getList() { - this.list = new FastList<>(); - list.add(1); - list.add(8); - list.add(5); - list.add(41); - list.add(31); - list.add(17); - list.add(23); - list.add(38); + this.list = FastList.newListWith(1, 8, 5, 41, 31, 17, 23, 38); } @Test diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/CollectPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/CollectPatternTest.java index 51591cd08c..ee384c2f9d 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/CollectPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/CollectPatternTest.java @@ -2,7 +2,8 @@ package com.baeldung.eclipsecollections; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.list.mutable.FastList; -import static org.junit.Assert.assertEquals; + +import org.assertj.core.api.Assertions; import org.junit.Test; public class CollectPatternTest { @@ -16,7 +17,7 @@ public class CollectPatternTest { MutableList lastNames = students.collect(Student::getLastName); - assertEquals(lastNames.get(0), "Hopkins"); - assertEquals(lastNames.get(1), "Adams"); + Assertions.assertThat(lastNames) + .containsExactly("Hopkins", "Adams"); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/ConvertContainerToAnotherTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/ConvertContainerToAnotherTest.java index b538abfa6e..4655431872 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/ConvertContainerToAnotherTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/ConvertContainerToAnotherTest.java @@ -1,9 +1,8 @@ package com.baeldung.eclipsecollections; -import static org.junit.Assert.assertTrue; - +import org.assertj.core.api.Assertions; import org.eclipse.collections.api.list.MutableList; -import org.eclipse.collections.impl.block.factory.Predicates; +import org.eclipse.collections.impl.list.mutable.FastList; import org.junit.Test; public class ConvertContainerToAnotherTest { @@ -12,9 +11,8 @@ public class ConvertContainerToAnotherTest { @Test public void whenConvertContainerToAnother_thenCorrect() { MutableList cars = (MutableList) ConvertContainerToAnother.convertToList(); - - assertTrue(cars.anySatisfy(Predicates.equal("Toyota"))); - assertTrue(cars.anySatisfy(Predicates.equal("Mercedes"))); - assertTrue(cars.anySatisfy(Predicates.equal("Volkswagen"))); + + Assertions.assertThat(cars) + .containsExactlyElementsOf(FastList.newListWith("Volkswagen", "Toyota", "Mercedes")); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/DetectPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/DetectPatternTest.java index fc643f2840..c5b5e1c412 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/DetectPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/DetectPatternTest.java @@ -1,10 +1,9 @@ package com.baeldung.eclipsecollections; +import org.assertj.core.api.Assertions; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.block.factory.Predicates; import org.eclipse.collections.impl.list.mutable.FastList; -import static org.junit.Assert.assertEquals; - import org.junit.Before; import org.junit.Test; @@ -14,21 +13,14 @@ public class DetectPatternTest { @Before public void getList() { - this.list = new FastList<>(); - list.add(1); - list.add(8); - list.add(5); - list.add(41); - list.add(31); - list.add(17); - list.add(23); - list.add(38); + this.list = FastList.newListWith(1, 8, 5, 41, 31, 17, 23, 38); } @Test public void whenDetect_thenCorrect() { Integer result = list.detect(Predicates.greaterThan(30)); - assertEquals((int) result, 41); + Assertions.assertThat(result) + .isEqualTo(41); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/FlatCollectTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/FlatCollectTest.java new file mode 100644 index 0000000000..021c72e91e --- /dev/null +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/FlatCollectTest.java @@ -0,0 +1,50 @@ +package com.baeldung.eclipsecollections; + +import org.assertj.core.api.Assertions; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.list.mutable.FastList; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class FlatCollectTest { + + MutableList addresses1; + MutableList addresses2; + MutableList addresses3; + MutableList addresses4; + + List expectedAddresses; + MutableList students; + + @Before + public void setup() { + String address1 = "73 Pacific St., Forest Hills, NY 11375"; + String address2 = "93 Bayport Ave., South Richmond Hill, NY 11419"; + String address3 = "548 Market St, San Francisco, CA 94104"; + String address4 = "8605 Santa Monica Blvd, West Hollywood, CA 90069"; + + this.addresses1 = FastList.newListWith(address1, address2); + this.addresses2 = FastList.newListWith(address3, address4); + Student student1 = new Student("John", "Hopkins", addresses1); + Student student2 = new Student("George", "Adams", addresses2); + this.addresses2 = FastList.newListWith(address3, address4); + this.students = FastList.newListWith(student1, student2); + this.expectedAddresses = new ArrayList<>(); + this.expectedAddresses.add("73 Pacific St., Forest Hills, NY 11375"); + this.expectedAddresses.add("93 Bayport Ave., South Richmond Hill, NY 11419"); + this.expectedAddresses.add("548 Market St, San Francisco, CA 94104"); + this.expectedAddresses.add("8605 Santa Monica Blvd, West Hollywood, CA 90069"); + } + + @Test + public void whenFlatCollect_thenCorrect() { + MutableList addresses = students.flatCollect(Student::getAddresses); + + Assertions.assertThat(addresses) + .containsExactlyElementsOf(this.expectedAddresses); + } +} diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java index e8d93a2af6..8cea575222 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/ForEachPatternTest.java @@ -1,13 +1,10 @@ package com.baeldung.eclipsecollections; -import org.eclipse.collections.api.block.procedure.Procedure; +import static org.junit.Assert.assertEquals; + import org.eclipse.collections.api.tuple.Pair; import org.eclipse.collections.impl.map.mutable.UnifiedMap; import org.eclipse.collections.impl.tuple.Tuples; -import static org.junit.Assert.assertEquals; - -import java.util.Map; - import org.junit.Test; public class ForEachPatternTest { diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/LazyIterationTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/LazyIterationTest.java index 8fe1286d41..9c216ecc87 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/LazyIterationTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/LazyIterationTest.java @@ -1,10 +1,9 @@ package com.baeldung.eclipsecollections; +import org.assertj.core.api.Assertions; import org.eclipse.collections.api.LazyIterable; import org.eclipse.collections.api.list.MutableList; -import org.eclipse.collections.impl.block.factory.Predicates; import org.eclipse.collections.impl.factory.Lists; -import static org.junit.Assert.assertTrue; import org.junit.Test; public class LazyIterationTest { @@ -19,8 +18,7 @@ public class LazyIterationTest { LazyIterable lazyStudents = students.asLazy(); LazyIterable lastNames = lazyStudents.collect(Student::getLastName); - assertTrue(lastNames.anySatisfy(Predicates.equal("Hopkins"))); - assertTrue(lastNames.anySatisfy(Predicates.equal("Adams"))); - assertTrue(lastNames.anySatisfy(Predicates.equal("Rodriguez"))); + Assertions.assertThat(lastNames) + .containsAll(Lists.mutable.with("Hopkins", "Adams", "Rodriguez")); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/PartitionPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/PartitionPatternTest.java index 3e52829824..c055413cd9 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/PartitionPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/PartitionPatternTest.java @@ -1,12 +1,9 @@ package com.baeldung.eclipsecollections; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - +import org.assertj.core.api.Assertions; import org.eclipse.collections.api.block.predicate.Predicate; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.api.partition.list.PartitionMutableList; -import org.eclipse.collections.impl.block.factory.Predicates; import org.eclipse.collections.impl.list.mutable.FastList; import org.junit.Before; import org.junit.Test; @@ -17,18 +14,9 @@ public class PartitionPatternTest { @Before public void getList() { - this.list = new FastList<>(); - list.add(1); - list.add(8); - list.add(5); - list.add(41); - list.add(31); - list.add(17); - list.add(23); - list.add(38); + this.list = FastList.newListWith(1, 8, 5, 41, 31, 17, 23, 38); } - @SuppressWarnings({ "unused" }) @Test public void whenAnySatisfiesCondition_thenCorrect() { MutableList numbers = list; @@ -48,14 +36,9 @@ public class PartitionPatternTest { MutableList smallerThanThirty = partitionedFolks.getRejected() .sortThis(); - assertEquals(1, (int) smallerThanThirty.getFirst()); - assertTrue(smallerThanThirty.anySatisfy(Predicates.equal(5))); - assertTrue(smallerThanThirty.anySatisfy(Predicates.equal(8))); - assertTrue(smallerThanThirty.anySatisfy(Predicates.equal(17))); - assertTrue(smallerThanThirty.anySatisfy(Predicates.equal(23))); - - assertTrue(greaterThanThirty.anySatisfy(Predicates.equal(31))); - assertTrue(greaterThanThirty.anySatisfy(Predicates.equal(38))); - assertTrue(greaterThanThirty.anySatisfy(Predicates.equal(41))); + Assertions.assertThat(smallerThanThirty) + .containsExactly(1, 5, 8, 17, 23); + Assertions.assertThat(greaterThanThirty) + .containsExactly(31, 38, 41); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/RejectPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/RejectPatternTest.java index 044a8203d6..1666c86333 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/RejectPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/RejectPatternTest.java @@ -1,27 +1,21 @@ package com.baeldung.eclipsecollections; +import org.assertj.core.api.Assertions; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.block.factory.Predicates; import org.eclipse.collections.impl.list.mutable.FastList; -import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; public class RejectPatternTest { MutableList list; + MutableList expectedList; @Before - public void getList() { - this.list = new FastList<>(); - list.add(1); - list.add(8); - list.add(5); - list.add(41); - list.add(31); - list.add(17); - list.add(23); - list.add(38); + public void setup() { + this.list = FastList.newListWith(1, 8, 5, 41, 31, 17, 23, 38); + this.expectedList = FastList.newListWith(1, 5, 8, 17, 23); } @Test @@ -29,10 +23,7 @@ public class RejectPatternTest { MutableList notGreaterThanThirty = list.reject(Predicates.greaterThan(30)) .sortThis(); - assertEquals(1, (int) notGreaterThanThirty.getFirst()); - assertEquals(5, (int) notGreaterThanThirty.get(1)); - assertEquals(8, (int) notGreaterThanThirty.get(2)); - assertEquals(17, (int) notGreaterThanThirty.get(3)); - assertEquals(23, (int) notGreaterThanThirty.getLast()); + Assertions.assertThat(notGreaterThanThirty) + .containsExactlyElementsOf(this.expectedList); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/SelectPatternTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/SelectPatternTest.java index 20c94f6028..d79c864fc5 100644 --- a/libraries/src/test/java/com/baeldung/eclipsecollections/SelectPatternTest.java +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/SelectPatternTest.java @@ -1,9 +1,9 @@ package com.baeldung.eclipsecollections; +import org.assertj.core.api.Assertions; import org.eclipse.collections.api.list.MutableList; import org.eclipse.collections.impl.block.factory.Predicates; import org.eclipse.collections.impl.list.mutable.FastList; -import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; @@ -13,15 +13,7 @@ public class SelectPatternTest { @Before public void getList() { - this.list = new FastList<>(); - list.add(1); - list.add(8); - list.add(5); - list.add(41); - list.add(31); - list.add(17); - list.add(23); - list.add(38); + this.list = FastList.newListWith(1, 8, 5, 41, 31, 17, 23, 38); } @Test @@ -29,9 +21,8 @@ public class SelectPatternTest { MutableList greaterThanThirty = list.select(Predicates.greaterThan(30)) .sortThis(); - assertEquals(31, (int) greaterThanThirty.getFirst()); - assertEquals(38, (int) greaterThanThirty.get(1)); - assertEquals(41, (int) greaterThanThirty.getLast()); + Assertions.assertThat(greaterThanThirty) + .containsExactly(31, 38, 41); } @SuppressWarnings("rawtypes") @@ -45,8 +36,7 @@ public class SelectPatternTest { public void givenListwhenSelectUsingLambda_thenCorrect() { MutableList greaterThanThirty = selectUsingLambda(); - assertEquals(31, (int) greaterThanThirty.getFirst()); - assertEquals(38, (int) greaterThanThirty.get(1)); - assertEquals(41, (int) greaterThanThirty.getLast()); + Assertions.assertThat(greaterThanThirty) + .containsExactly(31, 38, 41); } } diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/ZipTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/ZipTest.java new file mode 100644 index 0000000000..29f0c23954 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/ZipTest.java @@ -0,0 +1,34 @@ +package com.baeldung.eclipsecollections; + +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.tuple.Tuples; + +import org.assertj.core.api.Assertions; +import org.junit.Before; +import org.junit.Test; + +public class ZipTest { + + MutableList> expectedPairs; + + @SuppressWarnings("unchecked") + @Before + public void setup() { + Pair pair1 = Tuples.pair("1", "Porsche"); + Pair pair2 = Tuples.pair("2", "Volvo"); + Pair pair3 = Tuples.pair("3", "Toyota"); + expectedPairs = Lists.mutable.of(pair1, pair2, pair3); + } + + @Test + public void whenZip_thenCorrect() { + MutableList numbers = Lists.mutable.with("1", "2", "3", "Ignored"); + MutableList cars = Lists.mutable.with("Porsche", "Volvo", "Toyota"); + MutableList> pairs = numbers.zip(cars); + + Assertions.assertThat(pairs) + .containsExactlyElementsOf(this.expectedPairs); + } +} diff --git a/libraries/src/test/java/com/baeldung/eclipsecollections/ZipWithIndexTest.java b/libraries/src/test/java/com/baeldung/eclipsecollections/ZipWithIndexTest.java new file mode 100644 index 0000000000..a2d8be44ec --- /dev/null +++ b/libraries/src/test/java/com/baeldung/eclipsecollections/ZipWithIndexTest.java @@ -0,0 +1,33 @@ +package com.baeldung.eclipsecollections; + +import org.assertj.core.api.Assertions; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.factory.Lists; +import org.eclipse.collections.impl.list.mutable.FastList; +import org.eclipse.collections.impl.tuple.Tuples; +import org.junit.Before; +import org.junit.Test; + +public class ZipWithIndexTest { + + MutableList> expectedPairs; + + @SuppressWarnings("unchecked") + @Before + public void setup() { + Pair pair1 = Tuples.pair("Porsche", 0); + Pair pair2 = Tuples.pair("Volvo", 1); + Pair pair3 = Tuples.pair("Toyota", 2); + expectedPairs = Lists.mutable.of(pair1, pair2, pair3); + } + + @Test + public void whenZip_thenCorrect() { + MutableList cars = FastList.newListWith("Porsche", "Volvo", "Toyota"); + MutableList> pairs = cars.zipWithIndex(); + + Assertions.assertThat(pairs) + .containsExactlyElementsOf(this.expectedPairs); + } +} diff --git a/libraries/src/test/resources/book.csv b/libraries/src/test/resources/book.csv new file mode 100644 index 0000000000..d709152a5e --- /dev/null +++ b/libraries/src/test/resources/book.csv @@ -0,0 +1,3 @@ +author,title +Dan Simmons,Hyperion +Douglas Adams,The Hitchhiker's Guide to the Galaxy diff --git a/openl-tablets/pom.xml b/openl-tablets/pom.xml new file mode 100644 index 0000000000..77b9f47b38 --- /dev/null +++ b/openl-tablets/pom.xml @@ -0,0 +1,23 @@ + + 4.0.0 + com.baeldung.openltablets + openl-tablets + 0.0.1-SNAPSHOT + + UTF-8 + UTF-8 + 1.8 + + + + org.openl + org.openl.core + 5.19.4 + + + org.openl.rules + org.openl.rules + 5.19.4 + + + \ No newline at end of file diff --git a/openl-tablets/src/main/java/com/baeldung/openltablets/model/Case.java b/openl-tablets/src/main/java/com/baeldung/openltablets/model/Case.java new file mode 100644 index 0000000000..f9f5f4bd5f --- /dev/null +++ b/openl-tablets/src/main/java/com/baeldung/openltablets/model/Case.java @@ -0,0 +1,23 @@ +package com.baeldung.openltablets.model; + +public class Case { + + private User user; + private int hourOfDay; + + public User getUser() { + return user; + } + + public void setUser(final User user) { + this.user = user; + } + + public int getHourOfDay() { + return hourOfDay; + } + + public void setHourOfDay(final int hourOfDay) { + this.hourOfDay = hourOfDay; + } +} diff --git a/openl-tablets/src/main/java/com/baeldung/openltablets/model/Greeting.java b/openl-tablets/src/main/java/com/baeldung/openltablets/model/Greeting.java new file mode 100644 index 0000000000..5dc7bcd117 --- /dev/null +++ b/openl-tablets/src/main/java/com/baeldung/openltablets/model/Greeting.java @@ -0,0 +1,20 @@ +package com.baeldung.openltablets.model; + +public enum Greeting { + + GOOD_MORNING("Good Morning"), + GOOD_AFTERNOON("Good Afternoon"), + GOOD_EVENING("Good Evening"), + GOOD_NIGHT("Good Night"); + + private final String literal; + + private Greeting(final String literal) { + this.literal = literal; + } + + public String getLiteral() { + return literal; + } + +} \ No newline at end of file diff --git a/openl-tablets/src/main/java/com/baeldung/openltablets/model/User.java b/openl-tablets/src/main/java/com/baeldung/openltablets/model/User.java new file mode 100644 index 0000000000..8e45487497 --- /dev/null +++ b/openl-tablets/src/main/java/com/baeldung/openltablets/model/User.java @@ -0,0 +1,14 @@ +package com.baeldung.openltablets.model; + +public class User { + + private String name; + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/openl-tablets/src/main/java/com/baeldung/openltablets/rules/IRule.java b/openl-tablets/src/main/java/com/baeldung/openltablets/rules/IRule.java new file mode 100644 index 0000000000..857a6433ef --- /dev/null +++ b/openl-tablets/src/main/java/com/baeldung/openltablets/rules/IRule.java @@ -0,0 +1,7 @@ +package com.baeldung.openltablets.rules; + +import com.baeldung.openltablets.model.Case; + +public interface IRule { + void helloUser(final Case aCase, final Response response); +} \ No newline at end of file diff --git a/openl-tablets/src/main/java/com/baeldung/openltablets/rules/Main.java b/openl-tablets/src/main/java/com/baeldung/openltablets/rules/Main.java new file mode 100644 index 0000000000..34f5c48ed1 --- /dev/null +++ b/openl-tablets/src/main/java/com/baeldung/openltablets/rules/Main.java @@ -0,0 +1,31 @@ +package com.baeldung.openltablets.rules; + + +import java.time.LocalDateTime; + +import org.openl.rules.runtime.RulesEngineFactory; +import org.openl.runtime.EngineFactory; + +import com.baeldung.openltablets.model.Case; +import com.baeldung.openltablets.model.User; + +public class Main { + private IRule instance; + + public static void main(String[] args) { + Main rules = new Main(); + User user = new User(); + user.setName("Donald Duck"); + Case aCase = new Case(); + aCase.setUser(user); + aCase.setHourOfDay(23); + rules.process(aCase); + } + + public void process(Case aCase) { + final EngineFactory engineFactory = new RulesEngineFactory(getClass().getClassLoader() + .getResource("openltablets/HelloUser.xls"), IRule.class); + instance = engineFactory.newEngineInstance(); + instance.helloUser(aCase, new Response()); + } +} diff --git a/openl-tablets/src/main/java/com/baeldung/openltablets/rules/Response.java b/openl-tablets/src/main/java/com/baeldung/openltablets/rules/Response.java new file mode 100644 index 0000000000..27fa634866 --- /dev/null +++ b/openl-tablets/src/main/java/com/baeldung/openltablets/rules/Response.java @@ -0,0 +1,24 @@ +package com.baeldung.openltablets.rules; + +import java.util.HashMap; +import java.util.Map; + +public class Response { + private String result; + private Map map = new HashMap<>(); + + public Response() { } + + public String getResult() { + return result; + } + + public void setResult(final String s) { + result = s; + } + + public Map getMap() { + return map; + } + +} diff --git a/openl-tablets/src/main/resources/openltablets/HelloUser.xls b/openl-tablets/src/main/resources/openltablets/HelloUser.xls new file mode 100644 index 0000000000..1e85d0ce2d Binary files /dev/null and b/openl-tablets/src/main/resources/openltablets/HelloUser.xls differ diff --git a/pom.xml b/pom.xml index 8b3df8de0d..f2dd0ae48c 100644 --- a/pom.xml +++ b/pom.xml @@ -175,6 +175,7 @@ spring-mvc-webflow spring-mvc-xml spring-mvc-simple + spring-mvc-kotlin spring-security-openid spring-protobuf spring-quartz @@ -237,6 +238,7 @@ liquibase spring-boot-property-exp mockserver + undertow diff --git a/ratpack/README.md b/ratpack/README.md index 91c8e025f0..8215f74148 100644 --- a/ratpack/README.md +++ b/ratpack/README.md @@ -2,3 +2,4 @@ - [Introduction to Ratpack](http://www.baeldung.com/ratpack) - [Ratpack Google Guice Integration](http://www.baeldung.com/ratpack-google-guice) +- [Ratpack Integration with Spring Boot](http://www.baeldung.com/ratpack-spring-boot) diff --git a/rulebook/pom.xml b/rulebook/pom.xml new file mode 100644 index 0000000000..2a42e36d93 --- /dev/null +++ b/rulebook/pom.xml @@ -0,0 +1,15 @@ + + 4.0.0 + com.baeldung.rulebook + rulebook + 1.0.0-SNAPSHOT + + + + com.deliveredtechnologies + rulebook-core + 0.6.2 + + + \ No newline at end of file diff --git a/rulebook/src/main/java/com/baeldung/rulebook/HelloWorldRule.java b/rulebook/src/main/java/com/baeldung/rulebook/HelloWorldRule.java new file mode 100644 index 0000000000..c09772a3c6 --- /dev/null +++ b/rulebook/src/main/java/com/baeldung/rulebook/HelloWorldRule.java @@ -0,0 +1,17 @@ +package com.baeldung.rulebook; + +import com.deliveredtechnologies.rulebook.lang.RuleBookBuilder; +import com.deliveredtechnologies.rulebook.model.RuleBook; + +public class HelloWorldRule { + public RuleBook defineHelloWorldRules() { + + return RuleBookBuilder.create() + .addRule(rule -> rule.withNoSpecifiedFactType() + .then(f -> System.out.print("Hello "))) + .addRule(rule -> rule.withNoSpecifiedFactType() + .then(f -> System.out.println("World"))) + .build(); + + } +} diff --git a/rulebook/src/main/java/com/baeldung/rulebook/Launcher.java b/rulebook/src/main/java/com/baeldung/rulebook/Launcher.java new file mode 100644 index 0000000000..57965457ec --- /dev/null +++ b/rulebook/src/main/java/com/baeldung/rulebook/Launcher.java @@ -0,0 +1,12 @@ +package com.baeldung.rulebook; + +import com.deliveredtechnologies.rulebook.FactMap; + +public class Launcher { + + public static void main(String[] args) { + HelloWorldRule ruleBook = new HelloWorldRule(); + ruleBook.defineHelloWorldRules() + .run(new FactMap<>()); + } +} diff --git a/spring-5/README.md b/spring-5/README.md index 03b8121f90..4ce0fd4c79 100644 --- a/spring-5/README.md +++ b/spring-5/README.md @@ -8,5 +8,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Concurrent Test Execution in Spring 5](http://www.baeldung.com/spring-5-concurrent-tests) - [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) - [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) - - +- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) diff --git a/spring-activiti/README.md b/spring-activiti/README.md new file mode 100644 index 0000000000..fc6eea7f87 --- /dev/null +++ b/spring-activiti/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [A Guide to Activiti with Java](http://www.baeldung.com/java-activiti) diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/App.java b/spring-batch/src/main/java/org/baeldung/batch/App.java similarity index 96% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/App.java rename to spring-batch/src/main/java/org/baeldung/batch/App.java index 2ce4dae6e6..cea4e8d486 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/App.java +++ b/spring-batch/src/main/java/org/baeldung/batch/App.java @@ -1,4 +1,4 @@ -package org.baeldung.spring_batch_intro; +package org.baeldung.batch; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java similarity index 85% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java rename to spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java index 9973005c7c..7b19935cc8 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringBatchConfig.java @@ -1,11 +1,8 @@ -package org.baeldung.spring_batch_intro; +package org.baeldung.batch; -import java.net.MalformedURLException; -import java.text.ParseException; - -import org.baeldung.spring_batch_intro.model.Transaction; -import org.baeldung.spring_batch_intro.service.CustomItemProcessor; -import org.baeldung.spring_batch_intro.service.RecordFieldSetMapper; +import org.baeldung.batch.model.Transaction; +import org.baeldung.batch.service.CustomItemProcessor; +import org.baeldung.batch.service.RecordFieldSetMapper; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; @@ -26,6 +23,9 @@ import org.springframework.core.io.Resource; import org.springframework.oxm.Marshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; +import java.net.MalformedURLException; +import java.text.ParseException; + public class SpringBatchConfig { @Autowired private JobBuilderFactory jobs; @@ -43,7 +43,7 @@ public class SpringBatchConfig { public ItemReader itemReader() throws UnexpectedInputException, ParseException { FlatFileItemReader reader = new FlatFileItemReader(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); - String[] tokens = { "username", "userid", "transactiondate", "amount" }; + String[] tokens = {"username", "userid", "transactiondate", "amount"}; tokenizer.setNames(tokens); reader.setResource(inputCsv); DefaultLineMapper lineMapper = new DefaultLineMapper(); @@ -71,13 +71,13 @@ public class SpringBatchConfig { @Bean public Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); - marshaller.setClassesToBeBound(new Class[] { Transaction.class }); + marshaller.setClassesToBeBound(Transaction.class); return marshaller; } @Bean protected Step step1(ItemReader reader, ItemProcessor processor, ItemWriter writer) { - return steps.get("step1"). chunk(10).reader(reader).processor(processor).writer(writer).build(); + return steps.get("step1").chunk(10).reader(reader).processor(processor).writer(writer).build(); } @Bean(name = "firstBatchJob") diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java b/spring-batch/src/main/java/org/baeldung/batch/SpringConfig.java similarity index 98% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java rename to spring-batch/src/main/java/org/baeldung/batch/SpringConfig.java index ed7d302047..35abcb2d16 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/SpringConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.spring_batch_intro; +package org.baeldung.batch; import java.net.MalformedURLException; diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java b/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java similarity index 96% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java rename to spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java index 3b2b9610f2..0ce3a413ab 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java +++ b/spring-batch/src/main/java/org/baeldung/batch/model/Transaction.java @@ -1,4 +1,4 @@ -package org.baeldung.spring_batch_intro.model; +package org.baeldung.batch.model; import java.util.Date; diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/CustomMultiResourcePartitioner.java b/spring-batch/src/main/java/org/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java similarity index 97% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/CustomMultiResourcePartitioner.java rename to spring-batch/src/main/java/org/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java index 4cae69efbd..667e013c35 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/CustomMultiResourcePartitioner.java +++ b/spring-batch/src/main/java/org/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.baeldung.spring_batch_intro.partitioner; +package org.baeldung.batch.partitioner; import java.util.HashMap; import java.util.Map; diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionConfig.java b/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionConfig.java similarity index 84% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionConfig.java rename to spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionConfig.java index fe8339a8b4..ad3aee4a2e 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionConfig.java +++ b/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionConfig.java @@ -1,13 +1,7 @@ -package org.baeldung.spring_batch_intro.partitioner; +package org.baeldung.batch.partitioner; -import java.io.IOException; -import java.net.MalformedURLException; -import java.text.ParseException; - -import javax.sql.DataSource; - -import org.baeldung.spring_batch_intro.model.Transaction; -import org.baeldung.spring_batch_intro.service.RecordFieldSetMapper; +import org.baeldung.batch.model.Transaction; +import org.baeldung.batch.service.RecordFieldSetMapper; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; @@ -33,7 +27,6 @@ import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.task.TaskExecutor; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.oxm.Marshaller; @@ -41,6 +34,11 @@ import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.transaction.PlatformTransactionManager; +import javax.sql.DataSource; +import java.io.IOException; +import java.net.MalformedURLException; +import java.text.ParseException; + @Configuration @EnableBatchProcessing public class SpringbatchPartitionConfig { @@ -57,26 +55,26 @@ public class SpringbatchPartitionConfig { @Bean(name = "partitionerJob") public Job partitionerJob() throws UnexpectedInputException, MalformedURLException, ParseException { return jobs.get("partitionerJob") - .start(partitionStep()) - .build(); + .start(partitionStep()) + .build(); } @Bean public Step partitionStep() throws UnexpectedInputException, MalformedURLException, ParseException { return steps.get("partitionStep") - .partitioner("slaveStep", partitioner()) - .step(slaveStep()) - .taskExecutor(taskExecutor()) - .build(); + .partitioner("slaveStep", partitioner()) + .step(slaveStep()) + .taskExecutor(taskExecutor()) + .build(); } @Bean public Step slaveStep() throws UnexpectedInputException, MalformedURLException, ParseException { return steps.get("slaveStep") - . chunk(1) - .reader(itemReader(null)) - .writer(itemWriter(marshaller(), null)) - .build(); + .chunk(1) + .reader(itemReader(null)) + .writer(itemWriter(marshaller(), null)) + .build(); } @Bean @@ -95,12 +93,12 @@ public class SpringbatchPartitionConfig { @Bean @StepScope public FlatFileItemReader itemReader(@Value("#{stepExecutionContext[fileName]}") String filename) throws UnexpectedInputException, ParseException { - FlatFileItemReader reader = new FlatFileItemReader(); + FlatFileItemReader reader = new FlatFileItemReader<>(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); - String[] tokens = { "username", "userid", "transactiondate", "amount" }; + String[] tokens = {"username", "userid", "transactiondate", "amount"}; tokenizer.setNames(tokens); reader.setResource(new ClassPathResource("input/partitioner/" + filename)); - DefaultLineMapper lineMapper = new DefaultLineMapper(); + DefaultLineMapper lineMapper = new DefaultLineMapper<>(); lineMapper.setLineTokenizer(tokenizer); lineMapper.setFieldSetMapper(new RecordFieldSetMapper()); reader.setLinesToSkip(1); @@ -121,7 +119,7 @@ public class SpringbatchPartitionConfig { @Bean public Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); - marshaller.setClassesToBeBound(new Class[] { Transaction.class }); + marshaller.setClassesToBeBound(Transaction.class); return marshaller; } @@ -142,16 +140,15 @@ public class SpringbatchPartitionConfig { // JobRepositoryFactoryBean's methods Throws Generic Exception, // it would have been better to have a specific one factory.afterPropertiesSet(); - return (JobRepository) factory.getObject(); + return factory.getObject(); } private DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL) - .addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql") - .addScript("classpath:org/springframework/batch/core/schema-h2.sql") - .build(); - return db; + return builder.setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql") + .addScript("classpath:org/springframework/batch/core/schema-h2.sql") + .build(); } private PlatformTransactionManager getTransactionManager() { diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionerApp.java b/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java similarity index 95% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionerApp.java rename to spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java index 1d6d922969..e56afc591c 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/partitioner/SpringbatchPartitionerApp.java +++ b/spring-batch/src/main/java/org/baeldung/batch/partitioner/SpringbatchPartitionerApp.java @@ -1,4 +1,4 @@ -package org.baeldung.spring_batch_intro.partitioner; +package org.baeldung.batch.partitioner; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java b/spring-batch/src/main/java/org/baeldung/batch/service/CustomItemProcessor.java similarity index 71% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java rename to spring-batch/src/main/java/org/baeldung/batch/service/CustomItemProcessor.java index ebee1d2802..8ca7892fec 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java +++ b/spring-batch/src/main/java/org/baeldung/batch/service/CustomItemProcessor.java @@ -1,6 +1,6 @@ -package org.baeldung.spring_batch_intro.service; +package org.baeldung.batch.service; -import org.baeldung.spring_batch_intro.model.Transaction; +import org.baeldung.batch.model.Transaction; import org.springframework.batch.item.ItemProcessor; public class CustomItemProcessor implements ItemProcessor { diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java b/spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java similarity index 91% rename from spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java rename to spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java index 94f9e7d94e..fa6f0870aa 100644 --- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java +++ b/spring-batch/src/main/java/org/baeldung/batch/service/RecordFieldSetMapper.java @@ -1,9 +1,9 @@ -package org.baeldung.spring_batch_intro.service; +package org.baeldung.batch.service; import java.text.ParseException; import java.text.SimpleDateFormat; -import org.baeldung.spring_batch_intro.model.Transaction; +import org.baeldung.batch.model.Transaction; import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.validation.BindException; diff --git a/spring-batch/src/main/resources/spring-batch-intro.xml b/spring-batch/src/main/resources/spring-batch-intro.xml index 93606d232f..0f76dd50ff 100644 --- a/spring-batch/src/main/resources/spring-batch-intro.xml +++ b/spring-batch/src/main/resources/spring-batch-intro.xml @@ -22,14 +22,14 @@ + class="org.baeldung.batch.service.RecordFieldSetMapper" /> - + @@ -40,7 +40,7 @@ - org.baeldung.spring_batch_intro.model.Transaction + org.baeldung.batch.model.Transaction diff --git a/spring-boot-bootstrap/pom.xml b/spring-boot-bootstrap/pom.xml index 697a139eb5..9da37a3261 100644 --- a/spring-boot-bootstrap/pom.xml +++ b/spring-boot-bootstrap/pom.xml @@ -17,6 +17,25 @@ 1.5.3.RELEASE + + UTF-8 diff --git a/spring-boot-property-exp/README.md b/spring-boot-property-exp/README.md index 5b2552ade7..8a598e7a05 100644 --- a/spring-boot-property-exp/README.md +++ b/spring-boot-property-exp/README.md @@ -1,2 +1,18 @@ ## The Module Holds Sources for the Following Articles - - [Automatic Property Expansion with Spring Boot] (http://www.baeldung.com/property-expansion-spring-boot) \ No newline at end of file + - [Automatic Property Expansion with Spring Boot](http://www.baeldung.com/property-expansion-spring-boot) + +### Module property-exp-default-config + This module contains both a standard Maven Spring Boot build and the Gradle build which is Maven compatible. + + In order to execute the Maven example, run the following command: + + `mvn spring-boot:run` + + To execute the Gradle example: + +`gradle bootRun` + + ### Module property-exp-custom-config + This project is not using the standard Spring Boot parent and is configured manually. Run the following command: + + `mvn exec:java` \ No newline at end of file diff --git a/spring-boot-property-exp/property-exp-custom-config/pom.xml b/spring-boot-property-exp/property-exp-custom-config/pom.xml index cfce323eab..7822b31cf2 100644 --- a/spring-boot-property-exp/property-exp-custom-config/pom.xml +++ b/spring-boot-property-exp/property-exp-custom-config/pom.xml @@ -9,7 +9,7 @@ 4.0.0 com.baeldung - property-exp-custom + property-exp-custom-config 0.0.1-SNAPSHOT jar diff --git a/spring-boot-property-exp/property-exp-default-config/pom.xml b/spring-boot-property-exp/property-exp-default-config/pom.xml index 2544800e6a..0625916d32 100644 --- a/spring-boot-property-exp/property-exp-default-config/pom.xml +++ b/spring-boot-property-exp/property-exp-default-config/pom.xml @@ -11,7 +11,7 @@ com.baeldung - property-exp-default + property-exp-default-config 0.0.1-SNAPSHOT jar diff --git a/spring-cloud-bus/README.md b/spring-cloud-bus/README.md new file mode 100644 index 0000000000..c5410ca4e2 --- /dev/null +++ b/spring-cloud-bus/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Spring Cloud Bus](http://www.baeldung.com/spring-cloud-bus) diff --git a/spring-core/README.md b/spring-core/README.md index b0d0b8408c..237f8cd4e9 100644 --- a/spring-core/README.md +++ b/spring-core/README.md @@ -6,4 +6,6 @@ - [Constructor Injection in Spring with Lombok](http://www.baeldung.com/spring-injection-lombok) - [A Quick Guide to Spring @Value](http://www.baeldung.com/spring-value-annotation) - [Spring YAML Configuration](http://www.baeldung.com/spring-yaml) +- [Introduction to Spring’s StreamUtils](http://www.baeldung.com/spring-stream-utils) - [Using Spring @Value with Defaults](http://www.baeldung.com/spring-value-defaults) + diff --git a/spring-core/src/main/java/com/baeldung/autowired/TypesOfBeanInjectionSpring.java b/spring-core/src/main/java/com/baeldung/autowired/TypesOfBeanInjectionSpring.java new file mode 100644 index 0000000000..ca6018a21e --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/autowired/TypesOfBeanInjectionSpring.java @@ -0,0 +1,70 @@ +package com.baeldung.autowired; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Service; + +@SpringBootApplication +public class TypesOfBeanInjectionSpring { + private final UserService userService; + + @Autowired // the @Autowired can even be omitted, in case there's only one explicit constructor + public TypesOfBeanInjectionSpring(UserService userService) { + this.userService = userService; + } + + public static void main(String[] args) { + SpringApplication.run(TypesOfBeanInjectionSpring.class, args); + } + + @Bean + CommandLineRunner runIt() { + return args -> { + userService.listUsers() + .stream() + .forEach(System.out::println); + }; + } +} + +class User { + private String name; + + public User(String name) { + this.name = name; + } + + // getters and setters ... + public String getName() { + return this.name; + } + + public String toString() { + return name; + } + +} + +interface UserService { + List listUsers(); +} + +@Service +class UserServiceImpl implements UserService { + + @Override + public List listUsers() { + ArrayList users = new ArrayList<>(3); + users.add(new User("Snoopy")); + users.add(new User("Woodstock")); + users.add(new User("Charlie Brown")); + return users; + } + +} diff --git a/spring-core/src/test/java/com/baeldung/autowired/TypesOfBeanInjectionSpringIntegrationTest.java b/spring-core/src/test/java/com/baeldung/autowired/TypesOfBeanInjectionSpringIntegrationTest.java new file mode 100644 index 0000000000..206a062a57 --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/autowired/TypesOfBeanInjectionSpringIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.autowired; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TypesOfBeanInjectionSpringIntegrationTest { + @Autowired + UserService userService; + + private static final String[] expected = new String[] { "Snoopy", "Woodstock", "Charlie Brown" }; + + @Test + public void givenDI_whenInjectObject_thenUserNamesAreListed() { + Assert.assertArrayEquals(expected, userService.listUsers() + .stream() + .map(User::getName) + .toArray()); + } +} diff --git a/spring-hibernate5/pom.xml b/spring-hibernate5/pom.xml index e3309ff10b..dac43c4dd3 100644 --- a/spring-hibernate5/pom.xml +++ b/spring-hibernate5/pom.xml @@ -120,6 +120,12 @@ hsqldb ${hsqldb.version} + + + mysql + mysql-connector-java + ${mysql-connector-java.version} + com.h2database @@ -167,7 +173,7 @@ - 4.3.5.RELEASE + 4.3.10.RELEASE 1.10.6.RELEASE @@ -177,7 +183,8 @@ 5.2.10.Final - 8.5.15 + 8.0.7-dmr + 9.0.0.M26 1.1 2.3.4 1.4.195 diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/model/Employee.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/model/Employee.java new file mode 100644 index 0000000000..f1ad30b090 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/model/Employee.java @@ -0,0 +1,86 @@ +package com.baeldung.hibernate.manytomany.model; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinTable; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "Employee") +public class Employee implements Serializable { + @Id + @Column(name = "employee_id") + @GeneratedValue + private Long employeeId; + + @Column(name = "first_name") + private String firstName; + + @Column(name = "last_name") + private String lastName; + + @ManyToMany(cascade = { CascadeType.ALL }) + @JoinTable( + name = "Employee_Project", + joinColumns = { @JoinColumn(name = "employee_id") }, + inverseJoinColumns = { @JoinColumn(name = "project_id") } + ) + Set projects = new HashSet(); + + + public Employee() { + super(); + } + + public Employee(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public Employee(String firstName, String lastName, Set projects) { + this.firstName = firstName; + this.lastName = lastName; + this.projects = projects; + } + + + public Long getEmployeeId() { + return employeeId; + } + + public void setEmployeeId(Long employeeId) { + this.employeeId = employeeId; + } + + 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 Set getProjects() { + return projects; + } + + public void setProjects(Set projects) { + this.projects = projects; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/model/Project.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/model/Project.java new file mode 100644 index 0000000000..d6c049f33e --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/model/Project.java @@ -0,0 +1,61 @@ +package com.baeldung.hibernate.manytomany.model; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "Project") +public class Project implements Serializable { + + @Id + @Column(name = "project_id") + @GeneratedValue + private Long projectId; + + @Column(name = "title") + private String title; + + @ManyToMany(mappedBy = "projects") + private Set employees = new HashSet(); + + public Project() { + super(); + } + + public Project(String title) { + this.title = title; + } + + public Long getProjectId() { + return projectId; + } + + public void setProjectId(Long projectId) { + this.projectId = projectId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Set getEmployees() { + return employees; + } + + public void setEmployees(Set employees) { + this.employees = employees; + } + + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java new file mode 100644 index 0000000000..5f489dd027 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/manytomany/util/HibernateUtil.java @@ -0,0 +1,41 @@ +package com.baeldung.hibernate.manytomany.util; + +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.service.ServiceRegistry; +import com.baeldung.hibernate.manytomany.model.Employee; +import com.baeldung.hibernate.manytomany.model.Project; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + + private static SessionFactory buildSessionFactory() { + try { + // Create the SessionFactory from hibernate-annotation.cfg.xml + Configuration configuration = new Configuration(); + configuration.addAnnotatedClass(Employee.class); + configuration.addAnnotatedClass(Project.class); + configuration.configure("manytomany.cfg.xml"); + System.out.println("Hibernate Annotation Configuration loaded"); + + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()) + .build(); + System.out.println("Hibernate Annotation serviceRegistry created"); + + SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); + + return sessionFactory; + } catch (Throwable ex) { + System.err.println("Initial SessionFactory creation failed." + ex); + ex.printStackTrace(); + throw new ExceptionInInitializerError(ex); + } + } + + public static SessionFactory getSessionFactory() { + if (sessionFactory == null) + sessionFactory = buildSessionFactory(); + return sessionFactory; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java b/spring-hibernate5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java new file mode 100644 index 0000000000..6f359054b6 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/manytomany/spring/PersistenceConfig.java @@ -0,0 +1,70 @@ +package com.baeldung.manytomany.spring; + +import java.util.Properties; +import javax.sql.DataSource; +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.orm.hibernate4.HibernateTransactionManager; +import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + + + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-mysql.properties" }) +@ComponentScan({ "com.baeldung.hibernate.manytomany" }) +public class PersistenceConfig { + + @Autowired + private Environment env; + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.hibernate.manytomany" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); + dataSource.setUrl(env.getProperty("jdbc.url")); + dataSource.setUsername(env.getProperty("jdbc.user")); + dataSource.setPassword(env.getProperty("jdbc.pass")); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + //hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.show_sql", "true"); + + return hibernateProperties; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/IEmployeeDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/IEmployeeDao.java new file mode 100644 index 0000000000..d619807b64 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/IEmployeeDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.manytomany.dao; + +import com.baeldung.hibernate.manytomany.model.Employee; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IEmployeeDao extends IOperations{ + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/IProjectDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/IProjectDao.java new file mode 100644 index 0000000000..4a55714f8d --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/IProjectDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.manytomany.dao; + +import com.baeldung.hibernate.manytomany.model.Project; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IProjectDao extends IOperations{ + +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/impl/EmployeeDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/impl/EmployeeDao.java new file mode 100644 index 0000000000..b062c00ff9 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/impl/EmployeeDao.java @@ -0,0 +1,16 @@ +package com.baeldung.persistence.manytomany.dao.impl; + +import org.springframework.stereotype.Repository; +import com.baeldung.hibernate.manytomany.model.Employee; +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.manytomany.dao.IEmployeeDao; + +@Repository +public class EmployeeDao extends AbstractHibernateDao implements IEmployeeDao { + + public EmployeeDao() { + super(); + + setClazz(Employee.class); + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/impl/ProjectDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/impl/ProjectDao.java new file mode 100644 index 0000000000..772026fbc1 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/manytomany/dao/impl/ProjectDao.java @@ -0,0 +1,17 @@ +package com.baeldung.persistence.manytomany.dao.impl; + +import org.springframework.stereotype.Repository; +import com.baeldung.hibernate.manytomany.model.Project; +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.manytomany.dao.IProjectDao; + + +@Repository +public class ProjectDao extends AbstractHibernateDao implements IProjectDao { + + public ProjectDao() { + super(); + + setClazz(Project.class); + } +} diff --git a/spring-hibernate5/src/main/resources/manytomany.cfg.xml b/spring-hibernate5/src/main/resources/manytomany.cfg.xml new file mode 100644 index 0000000000..8a10fc1580 --- /dev/null +++ b/spring-hibernate5/src/main/resources/manytomany.cfg.xml @@ -0,0 +1,27 @@ + + + + + + com.mysql.jdbc.Driver + + + buddhinisam123 + + + jdbc:mysql://localhost:3306/spring_hibernate_many_to_many + + + root + + + org.hibernate.dialect.MySQLDialect + + + thread + + true + + diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/manytomany/HibernateManyToManyAnnotationJavaConfigMainIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/manytomany/HibernateManyToManyAnnotationJavaConfigMainIntegrationTest.java new file mode 100644 index 0000000000..61d821e85e --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/manytomany/HibernateManyToManyAnnotationJavaConfigMainIntegrationTest.java @@ -0,0 +1,53 @@ +package com.baeldung.hibernate.manytomany; + + +import java.util.HashSet; +import java.util.Set; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import com.baeldung.hibernate.manytomany.model.Employee; +import com.baeldung.hibernate.manytomany.model.Project; +import com.baeldung.manytomany.spring.PersistenceConfig; + + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class HibernateManyToManyAnnotationJavaConfigMainIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + private Session session; + + + @Before + public final void before() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @After + public final void after() { + session.getTransaction().commit(); + session.close(); + } + + @Test + public final void whenEntitiesAreCreated_thenNoExceptions() { + Set projects = new HashSet(); + projects.add(new Project("IT Project")); + projects.add(new Project("Networking Project")); + session.persist(new Employee("Peter", "Oven", projects)); + session.persist(new Employee("Allan", "Norman", projects)); + } + +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/manytomany/HibernateManyToManyAnnotationXMLConfigMainIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/manytomany/HibernateManyToManyAnnotationXMLConfigMainIntegrationTest.java new file mode 100644 index 0000000000..5308134fac --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/manytomany/HibernateManyToManyAnnotationXMLConfigMainIntegrationTest.java @@ -0,0 +1,84 @@ +package com.baeldung.hibernate.manytomany; + +import static org.junit.Assert.assertNotNull; +import static junit.framework.TestCase.assertEquals; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import com.baeldung.hibernate.manytomany.util.HibernateUtil; +import com.baeldung.hibernate.manytomany.model.Employee; +import com.baeldung.hibernate.manytomany.model.Project; + + +public class HibernateManyToManyAnnotationXMLConfigMainIntegrationTest { + private static SessionFactory sessionFactory; + + private Session session; + + + @BeforeClass + public static void beforeTests() { + sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + + @Test + public void givenSession_checkIfDatabaseIsPopulated() { + Employee employee1 = new Employee("Peter", "Oven"); + Set projects = new HashSet(); + projects = employee1.getProjects(); + int noProjects = projects.size(); + assertEquals(0,noProjects); + Project project1 = new Project("IT Project"); + assertNotNull(project1); + projects.add(project1); + Project project2 = new Project("Networking Project"); + assertNotNull(project2); + projects.add(project2); + employee1.setProjects(projects); + assertNotNull(employee1); + Employee employee2 = new Employee("Allan", "Norman"); + employee2.setProjects(projects); + assertNotNull(employee2); + + session.persist(employee1); + session.persist(employee2); + session.getTransaction().commit(); + session.close(); + + session = sessionFactory.openSession(); + session.beginTransaction(); + @SuppressWarnings("unchecked") + List projectList = session.createQuery("FROM Project").list(); + assertNotNull(projectList); + @SuppressWarnings("unchecked") + List employeeList = session.createQuery("FROM Employee").list(); + assertNotNull(employeeList); + } + + + @After + public void tearDown() { + session.getTransaction().commit(); + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } + +} diff --git a/spring-ldap/pom.xml b/spring-ldap/pom.xml index 16d4879f10..05baf8c66d 100644 --- a/spring-ldap/pom.xml +++ b/spring-ldap/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung @@ -97,6 +97,18 @@ test + + + + org.springframework.data + spring-data-ldap + 1.0.6.RELEASE + + + org.springframework.data + spring-data-jpa + 1.11.6.RELEASE + diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java b/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java new file mode 100644 index 0000000000..726fa53b02 --- /dev/null +++ b/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java @@ -0,0 +1,55 @@ +package com.baeldung.ldap.data.repository; + +import javax.naming.Name; + +import org.springframework.ldap.odm.annotations.Attribute; +import org.springframework.ldap.odm.annotations.Entry; +import org.springframework.ldap.odm.annotations.Id; + +@Entry(base = "ou=users", objectClasses = { "person", "inetOrgPerson", "top" }) +public class User { + + @Id + private Name id; + + private @Attribute(name = "cn") String username; + private @Attribute(name = "sn") String password; + + public User() { + } + + public User(String username, String password) { + this.username = username; + this.password = password; + } + + public Name getId() { + return id; + } + + public void setId(Name id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return username; + } + +} diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java b/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java new file mode 100644 index 0000000000..12dc0f7f14 --- /dev/null +++ b/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java @@ -0,0 +1,17 @@ +package com.baeldung.ldap.data.repository; + +import java.util.List; + +import org.springframework.data.ldap.repository.LdapRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends LdapRepository { + + User findByUsername(String username); + + User findByUsernameAndPassword(String username, String password); + + List findByUsernameLikeIgnoreCase(String username); + +} diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java b/spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java new file mode 100644 index 0000000000..1b04edb35b --- /dev/null +++ b/spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java @@ -0,0 +1,87 @@ +package com.baeldung.ldap.data.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.ldap.core.AttributesMapper; +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.support.LdapNameBuilder; + +import javax.naming.Name; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.List; + +public class LdapClient { + + @Autowired + private Environment env; + + @Autowired + private ContextSource contextSource; + + @Autowired + private LdapTemplate ldapTemplate; + + public void authenticate(final String username, final String password) { + contextSource.getContext("cn=" + username + ",ou=users," + env.getRequiredProperty("ldap.partitionSuffix"), password); + } + + public List search(final String username) { + return ldapTemplate.search( + "ou=users", + "cn=" + username, + (AttributesMapper) attrs -> (String) attrs + .get("cn") + .get()); + } + + public void create(final String username, final String password) { + Name dn = LdapNameBuilder + .newInstance() + .add("ou", "users") + .add("cn", username) + .build(); + DirContextAdapter context = new DirContextAdapter(dn); + + context.setAttributeValues("objectclass", new String[]{"top", "person", "organizationalPerson", "inetOrgPerson"}); + context.setAttributeValue("cn", username); + context.setAttributeValue("sn", username); + context.setAttributeValue("userPassword", digestSHA(password)); + + ldapTemplate.bind(context); + } + + public void modify(final String username, final String password) { + Name dn = LdapNameBuilder + .newInstance() + .add("ou", "users") + .add("cn", username) + .build(); + DirContextOperations context = ldapTemplate.lookupContext(dn); + + context.setAttributeValues("objectclass", new String[]{"top", "person", "organizationalPerson", "inetOrgPerson"}); + context.setAttributeValue("cn", username); + context.setAttributeValue("sn", username); + context.setAttributeValue("userPassword", digestSHA(password)); + + ldapTemplate.modifyAttributes(context); + } + + private String digestSHA(final String password) { + String base64; + try { + MessageDigest digest = MessageDigest.getInstance("SHA"); + digest.update(password.getBytes()); + base64 = Base64 + .getEncoder() + .encodeToString(digest.digest()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + return "{SHA}" + base64; + } +} diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java b/spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java new file mode 100644 index 0000000000..54954e3c9d --- /dev/null +++ b/spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java @@ -0,0 +1,63 @@ +package com.baeldung.ldap.data.service; + +import com.baeldung.ldap.data.repository.User; +import com.baeldung.ldap.data.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ldap.support.LdapUtils; +import org.springframework.stereotype.Service; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class UserService { + + @Autowired + private UserRepository userRepository; + + public Boolean authenticate(final String username, final String password) { + User user = userRepository.findByUsernameAndPassword(username, password); + return user != null; + } + + public List search(final String username) { + List userList = userRepository.findByUsernameLikeIgnoreCase(username); + if (userList == null) { + return Collections.emptyList(); + } + + return userList.stream() + .map(User::getUsername) + .collect(Collectors.toList()); + } + + public void create(final String username, final String password) { + User newUser = new User(username,digestSHA(password)); + newUser.setId(LdapUtils.emptyLdapName()); + userRepository.save(newUser); + + } + + public void modify(final String username, final String password) { + User user = userRepository.findByUsername(username); + user.setPassword(password); + userRepository.save(user); + } + + private String digestSHA(final String password) { + String base64; + try { + MessageDigest digest = MessageDigest.getInstance("SHA"); + digest.update(password.getBytes()); + base64 = Base64.getEncoder() + .encodeToString(digest.digest()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + return "{SHA}" + base64; + } +} diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java b/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java index 8572e5d1be..fb3000b2bd 100644 --- a/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java +++ b/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java @@ -1,5 +1,6 @@ package com.baeldung.ldap.javaconfig; +import com.baeldung.ldap.client.LdapClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -7,15 +8,15 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; +import org.springframework.data.ldap.repository.config.EnableLdapRepositories; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.core.support.LdapContextSource; -import com.baeldung.ldap.client.LdapClient; - @Configuration @PropertySource("classpath:application.properties") -@ComponentScan(basePackages = { "com.baeldung.ldap.*" }) +@ComponentScan(basePackages = {"com.baeldung.ldap.*"}) @Profile("default") +@EnableLdapRepositories(basePackages = "com.baeldung.ldap.**") public class AppConfig { @Autowired diff --git a/spring-ldap/src/main/resources/logback.xml b/spring-ldap/src/main/resources/logback.xml index ec0dc2469a..32b78577ee 100644 --- a/spring-ldap/src/main/resources/logback.xml +++ b/spring-ldap/src/main/resources/logback.xml @@ -7,13 +7,13 @@ - - + + - + - + \ No newline at end of file diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java b/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java index b65588dc38..f5b74d64c6 100644 --- a/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java +++ b/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java @@ -1,7 +1,6 @@ package com.baeldung.ldap.client; -import java.util.List; - +import com.baeldung.ldap.javaconfig.TestConfig; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; @@ -13,11 +12,11 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import com.baeldung.ldap.javaconfig.TestConfig; +import java.util.List; @RunWith(SpringJUnit4ClassRunner.class) @ActiveProfiles("testlive") -@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class) public class LdapClientLiveTest { private static final String USER2 = "TEST02"; diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryTest.java b/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryTest.java new file mode 100644 index 0000000000..9f38af9263 --- /dev/null +++ b/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryTest.java @@ -0,0 +1,67 @@ +package com.baeldung.ldap.client; + +import com.baeldung.ldap.data.service.UserService; +import com.baeldung.ldap.javaconfig.TestConfig; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ActiveProfiles("testlive") +@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class) +public class LdapDataRepositoryTest { + + private static final String USER2 = "TEST02"; + private static final String USER3 = "TEST03"; + private static final String USER4 = "TEST04"; + + private static final String USER2_PWD = "TEST02"; + private static final String USER3_PWD = "TEST03"; + private static final String USER4_PWD = "TEST04"; + + private static final String SEARCH_STRING = "TEST*"; + + @Autowired + private UserService userService; + + @Test + public void givenLdapClient_whenCorrectCredentials_thenSuccessfulLogin() { + Boolean isValid = userService.authenticate(USER3, USER3_PWD); + assertEquals(true, isValid); + } + + @Test + public void givenLdapClient_whenIncorrectCredentials_thenFailedLogin() { + Boolean isValid = userService.authenticate(USER3, USER2_PWD); + assertEquals(false, isValid); + } + + @Test + public void givenLdapClient_whenCorrectSearchFilter_thenEntriesReturned() { + List userList = userService.search(SEARCH_STRING); + assertThat(userList, Matchers.containsInAnyOrder(USER2, USER3)); + } + + @Test + public void givenLdapClientNotExists_whenDataProvided_thenNewUserCreated() { + userService.create(USER4, USER4_PWD); + userService.authenticate(USER4, USER4_PWD); + } + + @Test + public void givenLdapClientExists_whenDataProvided_thenExistingUserModified() { + userService.modify(USER2, USER3_PWD); + userService.authenticate(USER2, USER3_PWD); + } + +} diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java b/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java index e2968e977c..c6293982da 100644 --- a/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java +++ b/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java @@ -1,5 +1,6 @@ package com.baeldung.ldap.javaconfig; +import com.baeldung.ldap.client.LdapClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -8,15 +9,15 @@ import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; +import org.springframework.data.ldap.repository.config.EnableLdapRepositories; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.core.support.LdapContextSource; import org.springframework.ldap.test.TestContextSourceFactoryBean; -import com.baeldung.ldap.client.LdapClient; - @Configuration @PropertySource("classpath:test_application.properties") -@ComponentScan(basePackages = { "com.baeldung.ldap.*" }) +@ComponentScan(basePackages = {"com.baeldung.ldap.*"}) +@EnableLdapRepositories(basePackages = "com.baeldung.ldap.**") @Profile("testlive") public class TestConfig { @Autowired diff --git a/spring-mvc-kotlin/pom.xml b/spring-mvc-kotlin/pom.xml new file mode 100644 index 0000000000..087f02fc68 --- /dev/null +++ b/spring-mvc-kotlin/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + spring-mvc-kotlin + 0.1-SNAPSHOT + + spring-mvc-kotlin + + war + + + + org.jetbrains.kotlin + kotlin-stdlib-jre8 + 1.1.4 + + + org.jetbrains.kotlin + kotlin-reflect + 1.1.4 + + + + org.springframework + spring-web + 4.3.10.RELEASE + + + org.springframework + spring-webmvc + 4.3.10.RELEASE + + + javax.servlet + jstl + 1.2 + + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + 1.1.4 + + + + compile + compile + + compile + + + + + test-compile + test-compile + + test-compile + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt new file mode 100644 index 0000000000..4907e46efb --- /dev/null +++ b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt @@ -0,0 +1,37 @@ +package com.baeldung.kotlin.mvc + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.servlet.ViewResolver +import org.springframework.web.servlet.config.annotation.EnableWebMvc +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter +import org.springframework.web.servlet.view.InternalResourceViewResolver +import org.springframework.web.servlet.view.JstlView + + + + + +@EnableWebMvc +@Configuration +open class ApplicationWebConfig: WebMvcConfigurerAdapter() { + + override fun addViewControllers(registry: ViewControllerRegistry?) { + super.addViewControllers(registry) + + registry!!.addViewController("/welcome.html") + } + + @Bean + open fun viewResolver(): ViewResolver { + val bean = InternalResourceViewResolver() + + bean.setViewClass(JstlView::class.java) + bean.setPrefix("/WEB-INF/view/") + bean.setSuffix(".jsp") + + return bean + } + +} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebInitializer.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebInitializer.kt new file mode 100644 index 0000000000..a4d1614271 --- /dev/null +++ b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebInitializer.kt @@ -0,0 +1,19 @@ +package com.baeldung.kotlin.mvc + +import com.baeldung.kotlin.mvc.ApplicationWebConfig +import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer + +class ApplicationWebInitializer: AbstractAnnotationConfigDispatcherServletInitializer() { + + override fun getRootConfigClasses(): Array>? { + return null + } + + override fun getServletMappings(): Array { + return arrayOf("/") + } + + override fun getServletConfigClasses(): Array> { + return arrayOf(ApplicationWebConfig::class.java) + } +} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml b/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml new file mode 100644 index 0000000000..ffe83a66fa --- /dev/null +++ b/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-mvc-kotlin/src/main/webapp/WEB-INF/view/welcome.jsp new file mode 100644 index 0000000000..bdb6716889 --- /dev/null +++ b/spring-mvc-kotlin/src/main/webapp/WEB-INF/view/welcome.jsp @@ -0,0 +1,7 @@ + + Welcome + + +

This is the body of the welcome view 2

+ + \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/web.xml b/spring-mvc-kotlin/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000..cbee6a1b11 --- /dev/null +++ b/spring-mvc-kotlin/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + Spring Kotlin MVC Application + + + spring-web-mvc + org.springframework.web.servlet.DispatcherServlet + 1 + + contextConfigLocation + /WEB-INF/spring-web-config.xml + + + + + spring-web-mvc + / + + + \ No newline at end of file diff --git a/spring-rest/README.md b/spring-rest/README.md index 66c893e45f..2cea315188 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -15,3 +15,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Custom Media Type for a Spring REST API](http://www.baeldung.com/spring-rest-custom-media-type) - [HTTP PUT vs HTTP PATCH in a REST API](http://www.baeldung.com/http-put-patch-difference-spring) - [Exploring the Spring Boot TestRestTemplate](http://www.baeldung.com/spring-boot-testresttemplate) +- [Spring – Log Incoming Requests](http://www.baeldung.com/spring-http-logging) diff --git a/testing/README.md b/testing/README.md index 6338a52f3d..a691737e4f 100644 --- a/testing/README.md +++ b/testing/README.md @@ -12,3 +12,4 @@ - [Testing with Google Truth](http://www.baeldung.com/google-truth) - [Testing with JGoTesting](http://www.baeldung.com/jgotesting) - [Introduction to JUnitParams](http://www.baeldung.com/junit-params) +- [Cucumber Java 8 Support](http://www.baeldung.com/cucumber-java-8-support) diff --git a/undertow/pom.xml b/undertow/pom.xml new file mode 100644 index 0000000000..a0f2dc53ee --- /dev/null +++ b/undertow/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + com.baeldung.undertow + undertow + jar + 1.0-SNAPSHOT + undertow + http://maven.apache.org + + + 1.8 + 1.8 + + + + + io.undertow + undertow-core + 1.4.18.Final + + + io.undertow + undertow-servlet + 1.4.18.Final + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + com.baeldung.undertow.SimpleServer + + + + + + + + \ No newline at end of file diff --git a/undertow/src/main/java/com/baeldung/undertow/SimpleServer.java b/undertow/src/main/java/com/baeldung/undertow/SimpleServer.java new file mode 100644 index 0000000000..7f869746be --- /dev/null +++ b/undertow/src/main/java/com/baeldung/undertow/SimpleServer.java @@ -0,0 +1,16 @@ +package com.baeldung.undertow; + +import io.undertow.Undertow; +import io.undertow.util.Headers; + +public class SimpleServer { + + public static void main(String[] args) { + Undertow server = Undertow.builder().addHttpListener(8080, "localhost").setHandler(exchange -> { + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain"); + exchange.getResponseSender().send("Hello Baeldung"); + }).build(); + server.start(); + } + +} diff --git a/undertow/src/main/java/com/baeldung/undertow/ftp/FileServer.java b/undertow/src/main/java/com/baeldung/undertow/ftp/FileServer.java new file mode 100644 index 0000000000..90cad9ebbd --- /dev/null +++ b/undertow/src/main/java/com/baeldung/undertow/ftp/FileServer.java @@ -0,0 +1,20 @@ +package com.baeldung.undertow.ftp; + +import java.nio.file.Paths; + +import io.undertow.Undertow; +import io.undertow.server.handlers.resource.PathResourceManager; + +import static io.undertow.Handlers.resource; + +public class FileServer { + + public static void main(String[] args) { + Undertow server = Undertow.builder().addHttpListener(8080, "localhost") + .setHandler(resource(new PathResourceManager(Paths.get(System.getProperty("user.home")), 100)) + .setDirectoryListingEnabled(true)) + .build(); + server.start(); + } + +} diff --git a/undertow/src/main/java/com/baeldung/undertow/secure/CustomIdentityManager.java b/undertow/src/main/java/com/baeldung/undertow/secure/CustomIdentityManager.java new file mode 100644 index 0000000000..e0984f65a5 --- /dev/null +++ b/undertow/src/main/java/com/baeldung/undertow/secure/CustomIdentityManager.java @@ -0,0 +1,77 @@ +package com.baeldung.undertow.secure; + +import java.security.Principal; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import io.undertow.security.idm.Account; +import io.undertow.security.idm.Credential; +import io.undertow.security.idm.PasswordCredential; + +public class CustomIdentityManager implements io.undertow.security.idm.IdentityManager { + + private final Map users; + + CustomIdentityManager(final Map users) { + this.users = users; + } + + @Override + public Account verify(Account account) { + return account; + } + + @Override + public Account verify(Credential credential) { + return null; + } + + @Override + public Account verify(String id, Credential credential) { + Account account = getAccount(id); + if (account != null && verifyCredential(account, credential)) { + return account; + } + return null; + } + + private boolean verifyCredential(Account account, Credential credential) { + if (credential instanceof PasswordCredential) { + char[] password = ((PasswordCredential) credential).getPassword(); + char[] expectedPassword = users.get(account.getPrincipal().getName()); + + return Arrays.equals(password, expectedPassword); + } + return false; + } + + private Account getAccount(final String id) { + if (users.containsKey(id)) { + return new Account() { + + private static final long serialVersionUID = 1L; + + private final Principal principal = new Principal() { + @Override + public String getName() { + return id; + } + }; + + @Override + public Principal getPrincipal() { + return principal; + } + + @Override + public Set getRoles() { + return Collections.emptySet(); + } + }; + } + return null; + } + +} diff --git a/undertow/src/main/java/com/baeldung/undertow/secure/SecureServer.java b/undertow/src/main/java/com/baeldung/undertow/secure/SecureServer.java new file mode 100644 index 0000000000..6f520944db --- /dev/null +++ b/undertow/src/main/java/com/baeldung/undertow/secure/SecureServer.java @@ -0,0 +1,52 @@ +package com.baeldung.undertow.secure; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.undertow.Undertow; +import io.undertow.io.IoCallback; +import io.undertow.security.api.AuthenticationMechanism; +import io.undertow.security.api.AuthenticationMode; +import io.undertow.security.api.SecurityContext; +import io.undertow.security.handlers.AuthenticationCallHandler; +import io.undertow.security.handlers.AuthenticationConstraintHandler; +import io.undertow.security.handlers.AuthenticationMechanismsHandler; +import io.undertow.security.handlers.SecurityInitialHandler; +import io.undertow.security.idm.IdentityManager; +import io.undertow.security.impl.BasicAuthenticationMechanism; +import io.undertow.server.HttpHandler; +import io.undertow.server.HttpServerExchange; + +public class SecureServer { + + public static void main(String[] args) { + final Map users = new HashMap<>(2); + users.put("root", "password".toCharArray()); + users.put("admin", "password".toCharArray()); + + final IdentityManager idm = new CustomIdentityManager(users); + + Undertow server = Undertow.builder().addHttpListener(8080, "localhost").setHandler(addSecurity((exchange) -> { + final SecurityContext context = exchange.getSecurityContext(); + exchange.getResponseSender().send("Hello " + context.getAuthenticatedAccount().getPrincipal().getName(), + IoCallback.END_EXCHANGE); + }, idm)).build(); + + server.start(); + + } + + private static HttpHandler addSecurity(final HttpHandler toWrap, final IdentityManager identityManager) { + HttpHandler handler = toWrap; + handler = new AuthenticationCallHandler(handler); + handler = new AuthenticationConstraintHandler(handler); + final List mechanisms = Collections + . singletonList(new BasicAuthenticationMechanism("Baeldung_Realm")); + handler = new AuthenticationMechanismsHandler(handler, mechanisms); + handler = new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, handler); + return handler; + } + +} diff --git a/undertow/src/main/java/com/baeldung/undertow/socket/SocketServer.java b/undertow/src/main/java/com/baeldung/undertow/socket/SocketServer.java new file mode 100644 index 0000000000..9e0e065c3a --- /dev/null +++ b/undertow/src/main/java/com/baeldung/undertow/socket/SocketServer.java @@ -0,0 +1,36 @@ +package com.baeldung.undertow.socket; + +import io.undertow.Undertow; +import io.undertow.server.handlers.resource.ClassPathResourceManager; +import io.undertow.websockets.core.AbstractReceiveListener; +import io.undertow.websockets.core.BufferedTextMessage; +import io.undertow.websockets.core.WebSocketChannel; +import io.undertow.websockets.core.WebSockets; + +import static io.undertow.Handlers.path; +import static io.undertow.Handlers.resource; +import static io.undertow.Handlers.websocket; + +public class SocketServer { + + public static void main(String[] args) { + Undertow server = Undertow.builder().addHttpListener(8080, "localhost") + .setHandler(path().addPrefixPath("/baeldungApp", websocket((exchange, channel) -> { + channel.getReceiveSetter().set(new AbstractReceiveListener() { + @Override + protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) { + final String messageData = message.getData(); + for (WebSocketChannel session : channel.getPeerConnections()) { + WebSockets.sendText(messageData, session, null); + } + } + }); + channel.resumeReceives(); + })).addPrefixPath("/", resource(new ClassPathResourceManager(SocketServer.class.getClassLoader(), + SocketServer.class.getPackage())).addWelcomeFiles("index.html"))) + .build(); + + server.start(); + } + +} diff --git a/vavr/README.md b/vavr/README.md index c4155c2680..d7816f3f9f 100644 --- a/vavr/README.md +++ b/vavr/README.md @@ -5,3 +5,4 @@ - [Property Testing Example With Vavr](http://www.baeldung.com/javaslang-property-testing) - [Exceptions in Lambda Expression Using Vavr](http://www.baeldung.com/exceptions-using-vavr) - [Vavr (ex-Javaslang) Support in Spring Data](http://www.baeldung.com/spring-vavr) +