Merge branch 'master' of https://github.com/eugenp/tutorials into BAEL-1525-Check-if-a-String-is-a-palindrome
This commit is contained in:
commit
604f5b1535
|
@ -11,6 +11,7 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -116,18 +117,20 @@ public class HttpClientTest {
|
||||||
.GET()
|
.GET()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
ExecutorService executorService = Executors.newFixedThreadPool(2);
|
||||||
|
|
||||||
CompletableFuture<HttpResponse<String>> response1 = HttpClient.newBuilder()
|
CompletableFuture<HttpResponse<String>> response1 = HttpClient.newBuilder()
|
||||||
.executor(Executors.newFixedThreadPool(2))
|
.executor(executorService)
|
||||||
.build()
|
.build()
|
||||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||||
|
|
||||||
CompletableFuture<HttpResponse<String>> response2 = HttpClient.newBuilder()
|
CompletableFuture<HttpResponse<String>> response2 = HttpClient.newBuilder()
|
||||||
.executor(Executors.newFixedThreadPool(2))
|
.executor(executorService)
|
||||||
.build()
|
.build()
|
||||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||||
|
|
||||||
CompletableFuture<HttpResponse<String>> response3 = HttpClient.newBuilder()
|
CompletableFuture<HttpResponse<String>> response3 = HttpClient.newBuilder()
|
||||||
.executor(Executors.newFixedThreadPool(2))
|
.executor(executorService)
|
||||||
.build()
|
.build()
|
||||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,16 @@
|
||||||
package com.baeldung.javac;
|
package com.baeldung.javac;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Data implements Serializable {
|
public class Data {
|
||||||
static List<String> textList = new ArrayList();
|
List<String> textList = new ArrayList();
|
||||||
|
|
||||||
private static void addText() {
|
public void addText(String text) {
|
||||||
textList.add("baeldung");
|
textList.add(text);
|
||||||
textList.add(".");
|
|
||||||
textList.add("com");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getTextList() {
|
public List getTextList() {
|
||||||
this.addText();
|
return this.textList;
|
||||||
List<String> result = new ArrayList<String>();
|
|
||||||
String firstElement = (String) textList.get(0);
|
|
||||||
switch (firstElement) {
|
|
||||||
case "baeldung":
|
|
||||||
result.add("baeldung");
|
|
||||||
case "com":
|
|
||||||
result.add("com");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -81,6 +81,7 @@ public class HibernateUtil {
|
||||||
metadataSources.addAnnotatedClass(Bag.class);
|
metadataSources.addAnnotatedClass(Bag.class);
|
||||||
metadataSources.addAnnotatedClass(PointEntity.class);
|
metadataSources.addAnnotatedClass(PointEntity.class);
|
||||||
metadataSources.addAnnotatedClass(PolygonEntity.class);
|
metadataSources.addAnnotatedClass(PolygonEntity.class);
|
||||||
|
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pojo.Person.class);
|
||||||
|
|
||||||
Metadata metadata = metadataSources.buildMetadata();
|
Metadata metadata = metadataSources.buildMetadata();
|
||||||
return metadata.getSessionFactoryBuilder()
|
return metadata.getSessionFactoryBuilder()
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.hibernate.converters;
|
||||||
|
|
||||||
|
import javax.persistence.AttributeConverter;
|
||||||
|
import javax.persistence.Converter;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.pojo.PersonName;
|
||||||
|
|
||||||
|
@Converter
|
||||||
|
public class PersonNameConverter implements AttributeConverter<PersonName, String> {
|
||||||
|
|
||||||
|
private static final String SEPARATOR = ", ";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String convertToDatabaseColumn(PersonName person) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (person.getSurname() != null) {
|
||||||
|
sb.append(person.getSurname());
|
||||||
|
sb.append(SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (person.getName() != null) {
|
||||||
|
sb.append(person.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PersonName convertToEntityAttribute(String dbPerson) {
|
||||||
|
String[] pieces = dbPerson.split(SEPARATOR);
|
||||||
|
|
||||||
|
if (pieces == null || pieces.length != 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PersonName personName = new PersonName();
|
||||||
|
personName.setSurname(pieces[0]);
|
||||||
|
personName.setName(pieces[1]);
|
||||||
|
|
||||||
|
return personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import org.hibernate.Interceptor;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
public class CustomInterceptorImpl implements Interceptor {
|
public class CustomInterceptorImpl implements Interceptor, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
|
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Convert;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.converters.PersonNameConverter;
|
||||||
|
|
||||||
|
@Entity(name = "PersonTable")
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Convert(converter = PersonNameConverter.class)
|
||||||
|
private PersonName personName;
|
||||||
|
|
||||||
|
public PersonName getPersonName() {
|
||||||
|
return personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonName(PersonName personName) {
|
||||||
|
this.personName = personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class PersonName implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7883094644631050150L;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String surname;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname() {
|
||||||
|
return surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurname(String surname) {
|
||||||
|
this.surname = surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.baeldung.hibernate.converter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.HibernateUtil;
|
||||||
|
import com.baeldung.hibernate.pojo.Person;
|
||||||
|
import com.baeldung.hibernate.pojo.PersonName;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class PersonNameConverterTest {
|
||||||
|
|
||||||
|
private Session session;
|
||||||
|
private Transaction transaction;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws IOException {
|
||||||
|
session = HibernateUtil.getSessionFactory()
|
||||||
|
.openSession();
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
|
||||||
|
session.createNativeQuery("delete from personTable")
|
||||||
|
.executeUpdate();
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
transaction.rollback();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonName_WhenSaving_ThenNameAndSurnameConcat() {
|
||||||
|
final String name = "name";
|
||||||
|
final String surname = "surname";
|
||||||
|
|
||||||
|
PersonName personName = new PersonName();
|
||||||
|
personName.setName(name);
|
||||||
|
personName.setSurname(surname);
|
||||||
|
|
||||||
|
Person person = new Person();
|
||||||
|
person.setPersonName(personName);
|
||||||
|
|
||||||
|
Long id = (Long) session.save(person);
|
||||||
|
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
|
||||||
|
String dbPersonName = (String) session.createNativeQuery("select p.personName from PersonTable p where p.id = :id")
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals(surname + ", " + name, dbPersonName);
|
||||||
|
|
||||||
|
Person dbPerson = session.createNativeQuery("select * from PersonTable p where p.id = :id", Person.class)
|
||||||
|
.setParameter("id", id)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
assertEquals(dbPerson.getPersonName()
|
||||||
|
.getName(), name);
|
||||||
|
assertEquals(dbPerson.getPersonName()
|
||||||
|
.getSurname(), surname);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
### Relevant Article:
|
### Relevant Article:
|
||||||
- [Introduction to using InfluxDB with Java](http://www.baeldung.com/using-influxdb-with-java/)
|
- [Introduction to using InfluxDB with Java](http://www.baeldung.com/using-influxdb-with-java/)
|
||||||
- [Using InfluxDB with Java](http://www.baeldung.com/java-influxdb)
|
|
||||||
|
|
||||||
### Overview
|
### Overview
|
||||||
This Maven project contains the Java code for the article linked above.
|
This Maven project contains the Java code for the article linked above.
|
||||||
|
|
|
@ -8,7 +8,6 @@ import org.influxdb.dto.*;
|
||||||
import org.influxdb.impl.InfluxDBResultMapper;
|
import org.influxdb.impl.InfluxDBResultMapper;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -103,7 +102,7 @@ public class InfluxDBConnectionLiveTest {
|
||||||
// another brief pause.
|
// another brief pause.
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
|
|
||||||
List<MemoryPoint> memoryPointList = getPoints(connection, "Select * from memory", "baeldung");
|
List<com.baeldung.influxdb.MemoryPoint> memoryPointList = getPoints(connection, "Select * from memory", "baeldung");
|
||||||
|
|
||||||
assertEquals(10, memoryPointList.size());
|
assertEquals(10, memoryPointList.size());
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
## Reliable Messaging with JGroups Tutorial Project
|
||||||
|
|
||||||
|
### Relevant Article:
|
||||||
|
- [Reliable Messaging with JGroups](http://www.baeldung.com/reliable-messaging-with-jgroups/)
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
This Maven project contains the Java code for the article linked above.
|
||||||
|
|
||||||
|
### Package Organization
|
||||||
|
Java classes for the intro tutorial are in the org.baeldung.jgroups package.
|
||||||
|
|
||||||
|
|
||||||
|
### Running the tests
|
||||||
|
|
||||||
|
```
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jgroups</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>jgroups</name>
|
||||||
|
<description>Reliable Messaging with JGroups Tutorial</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jgroups</groupId>
|
||||||
|
<artifactId>jgroups</artifactId>
|
||||||
|
<version>4.0.10.Final</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-cli</groupId>
|
||||||
|
<artifactId>commons-cli</artifactId>
|
||||||
|
<version>1.4</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,212 @@
|
||||||
|
package com.baeldung.jgroups;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
import org.jgroups.*;
|
||||||
|
import org.jgroups.util.Util;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class JGroupsMessenger extends ReceiverAdapter {
|
||||||
|
|
||||||
|
private JChannel channel;
|
||||||
|
private String userName;
|
||||||
|
private String clusterName;
|
||||||
|
private View lastView;
|
||||||
|
private boolean running = true;
|
||||||
|
|
||||||
|
// Our shared state
|
||||||
|
private Integer messageCount = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to a JGroups cluster using command line options
|
||||||
|
* @param args command line arguments
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private void start(String[] args) throws Exception {
|
||||||
|
processCommandline(args);
|
||||||
|
|
||||||
|
// Create the channel
|
||||||
|
// This file could be moved, or made a command line option.
|
||||||
|
channel = new JChannel("src/main/resources/udp.xml");
|
||||||
|
|
||||||
|
// Set a name
|
||||||
|
channel.name(userName);
|
||||||
|
|
||||||
|
// Register for callbacks
|
||||||
|
channel.setReceiver(this);
|
||||||
|
|
||||||
|
// Ignore our messages
|
||||||
|
channel.setDiscardOwnMessages(true);
|
||||||
|
|
||||||
|
// Connect
|
||||||
|
channel.connect(clusterName);
|
||||||
|
|
||||||
|
// Start state transfer
|
||||||
|
channel.getState(null, 0);
|
||||||
|
|
||||||
|
// Do the things
|
||||||
|
processInput();
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
channel.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quick and dirty implementaton of commons cli for command line args
|
||||||
|
* @param args the command line args
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
private void processCommandline(String[] args) throws ParseException {
|
||||||
|
|
||||||
|
// Options, parser, friendly help
|
||||||
|
Options options = new Options();
|
||||||
|
CommandLineParser parser = new DefaultParser();
|
||||||
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
|
|
||||||
|
options.addOption("u", "user", true, "User name")
|
||||||
|
.addOption("c", "cluster", true, "Cluster name");
|
||||||
|
|
||||||
|
CommandLine line = parser.parse(options, args);
|
||||||
|
|
||||||
|
if (line.hasOption("user")) {
|
||||||
|
userName = line.getOptionValue("user");
|
||||||
|
} else {
|
||||||
|
formatter.printHelp("JGroupsMessenger: need a user name.\n", options);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.hasOption("cluster")) {
|
||||||
|
clusterName = line.getOptionValue("cluster");
|
||||||
|
} else {
|
||||||
|
formatter.printHelp("JGroupsMessenger: need a cluster name.\n", options);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start it up
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new JGroupsMessenger().start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void viewAccepted(View newView) {
|
||||||
|
|
||||||
|
// Save view if this is the first
|
||||||
|
if (lastView == null) {
|
||||||
|
System.out.println("Received initial view:");
|
||||||
|
newView.forEach(System.out::println);
|
||||||
|
} else {
|
||||||
|
// Compare to last view
|
||||||
|
System.out.println("Received new view.");
|
||||||
|
|
||||||
|
List<Address> newMembers = View.newMembers(lastView, newView);
|
||||||
|
System.out.println("New members: ");
|
||||||
|
newMembers.forEach(System.out::println);
|
||||||
|
|
||||||
|
List<Address> exMembers = View.leftMembers(lastView, newView);
|
||||||
|
System.out.println("Exited members:");
|
||||||
|
exMembers.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
lastView = newView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop on console input until we see 'x' to exit
|
||||||
|
*/
|
||||||
|
private void processInput() throws Exception {
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
while (running) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Get a destination, <enter> means broadcast
|
||||||
|
Address destination = null;
|
||||||
|
System.out.print("Enter a destination: ");
|
||||||
|
System.out.flush();
|
||||||
|
String destinationName = in.readLine().toLowerCase();
|
||||||
|
|
||||||
|
if (destinationName.equals("x")) {
|
||||||
|
running = false;
|
||||||
|
continue;
|
||||||
|
} else if (!destinationName.isEmpty()) {
|
||||||
|
destination = getAddress(destinationName)
|
||||||
|
. orElseThrow(() -> new Exception("Destination not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept a string to send
|
||||||
|
System.out.print("Enter a message: ");
|
||||||
|
System.out.flush();
|
||||||
|
String line = in.readLine().toLowerCase();
|
||||||
|
sendMessage(destination, line);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Exiting.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send message from here
|
||||||
|
* @param destination the destination
|
||||||
|
* @param messageString the message
|
||||||
|
*/
|
||||||
|
private void sendMessage(Address destination, String messageString) {
|
||||||
|
try {
|
||||||
|
System.out.println("Sending " + messageString + " to " + destination);
|
||||||
|
Message message = new Message(destination, messageString);
|
||||||
|
channel.send(message);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
System.err.println("Exception sending message: " + exception.getMessage());
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receive(Message message) {
|
||||||
|
// Print source and dest with message
|
||||||
|
String line = "Message received from: " + message.getSrc() + " to: " + message.getDest() + " -> " + message.getObject();
|
||||||
|
|
||||||
|
// Only track the count of broadcast messages
|
||||||
|
// Tracking direct message would make for a pointless state
|
||||||
|
if (message.getDest() == null) {
|
||||||
|
messageCount++;
|
||||||
|
System.out.println("Message count: " + messageCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getState(OutputStream output) throws Exception {
|
||||||
|
// Serialize into the stream
|
||||||
|
Util.objectToStream(messageCount, new DataOutputStream(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setState(InputStream input) {
|
||||||
|
|
||||||
|
// NOTE: since we know that incrementing the count and transferring the state
|
||||||
|
// is done inside the JChannel's thread, we don't have to worry about synchronizing
|
||||||
|
// messageCount. For production code it should be synchronized!
|
||||||
|
try {
|
||||||
|
// Deserialize
|
||||||
|
messageCount = Util.objectFromStream(new DataInputStream(input));
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Error deserialing state!");
|
||||||
|
}
|
||||||
|
System.out.println(messageCount + " is the current messagecount.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Optional<Address> getAddress(String name) {
|
||||||
|
View view = channel.view();
|
||||||
|
return view.getMembers().stream().filter(address -> name.equals(address.toString())).findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<config xmlns="urn:org:jgroups"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd">
|
||||||
|
<UDP
|
||||||
|
mcast_port="${jgroups.udp.mcast_port:45588}"
|
||||||
|
ip_ttl="4"
|
||||||
|
tos="8"
|
||||||
|
ucast_recv_buf_size="5M"
|
||||||
|
ucast_send_buf_size="5M"
|
||||||
|
mcast_recv_buf_size="5M"
|
||||||
|
mcast_send_buf_size="5M"
|
||||||
|
max_bundle_size="64K"
|
||||||
|
enable_diagnostics="true"
|
||||||
|
thread_naming_pattern="cl"
|
||||||
|
|
||||||
|
thread_pool.min_threads="0"
|
||||||
|
thread_pool.max_threads="20"
|
||||||
|
thread_pool.keep_alive_time="30000"/>
|
||||||
|
|
||||||
|
<PING />
|
||||||
|
<MERGE3 max_interval="30000"
|
||||||
|
min_interval="10000"/>
|
||||||
|
<FD_SOCK/>
|
||||||
|
<FD_ALL/>
|
||||||
|
<VERIFY_SUSPECT timeout="1500" />
|
||||||
|
<BARRIER />
|
||||||
|
<pbcast.NAKACK2 xmit_interval="500"
|
||||||
|
xmit_table_num_rows="100"
|
||||||
|
xmit_table_msgs_per_row="2000"
|
||||||
|
xmit_table_max_compaction_time="30000"
|
||||||
|
use_mcast_xmit="false"
|
||||||
|
discard_delivered_msgs="true"/>
|
||||||
|
<UNICAST3 xmit_interval="500"
|
||||||
|
xmit_table_num_rows="100"
|
||||||
|
xmit_table_msgs_per_row="2000"
|
||||||
|
xmit_table_max_compaction_time="60000"
|
||||||
|
conn_expiry_timeout="0"/>
|
||||||
|
<pbcast.STABLE desired_avg_gossip="50000"
|
||||||
|
max_bytes="4M"/>
|
||||||
|
<pbcast.GMS print_local_addr="true" join_timeout="2000"/>
|
||||||
|
<UFC max_credits="2M"
|
||||||
|
min_threshold="0.4"/>
|
||||||
|
<MFC max_credits="2M"
|
||||||
|
min_threshold="0.4"/>
|
||||||
|
<FRAG2 frag_size="60K" />
|
||||||
|
<RSVP resend_interval="2000" timeout="10000"/>
|
||||||
|
<pbcast.STATE_TRANSFER />
|
||||||
|
</config>
|
|
@ -59,6 +59,7 @@
|
||||||
- [Intro to JDO Queries 2/2](http://www.baeldung.com/jdo-queries)
|
- [Intro to JDO Queries 2/2](http://www.baeldung.com/jdo-queries)
|
||||||
- [Guide to google-http-client](http://www.baeldung.com/google-http-client)
|
- [Guide to google-http-client](http://www.baeldung.com/google-http-client)
|
||||||
- [Interact with Google Sheets from Java](http://www.baeldung.com/google-sheets-java-client)
|
- [Interact with Google Sheets from Java](http://www.baeldung.com/google-sheets-java-client)
|
||||||
|
- [Programatically Create, Configure, and Run a Tomcat Server] (http://www.baeldung.com/tomcat-programmatic-setup)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -716,6 +716,13 @@
|
||||||
<classifier>test</classifier>
|
<classifier>test</classifier>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- tomcat -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.milyn</groupId>
|
<groupId>org.milyn</groupId>
|
||||||
<artifactId>milyn-smooks-all</artifactId>
|
<artifactId>milyn-smooks-all</artifactId>
|
||||||
|
@ -802,6 +809,7 @@
|
||||||
<kafka.version>1.0.0</kafka.version>
|
<kafka.version>1.0.0</kafka.version>
|
||||||
<smooks.version>1.7.0</smooks.version>
|
<smooks.version>1.7.0</smooks.version>
|
||||||
<docker.version>3.0.14</docker.version>
|
<docker.version>3.0.14</docker.version>
|
||||||
|
<tomcat.version>8.5.24</tomcat.version>
|
||||||
<async.http.client.version>2.2.0</async.http.client.version>
|
<async.http.client.version>2.2.0</async.http.client.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.tomcat;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.annotation.WebFilter;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 1/14/18.
|
||||||
|
*/
|
||||||
|
@WebFilter(urlPatterns = "/my-servlet/*")
|
||||||
|
public class MyFilter implements Filter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
System.out.println("Filtering stuff...");
|
||||||
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||||
|
httpResponse.addHeader("myHeader", "myHeaderValue");
|
||||||
|
chain.doFilter(request, httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.tomcat;
|
||||||
|
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 1/10/18.
|
||||||
|
*/
|
||||||
|
@WebServlet(
|
||||||
|
name = "com.baeldung.tomcat.programmatic.MyServlet",
|
||||||
|
urlPatterns = {"/my-servlet"}
|
||||||
|
)
|
||||||
|
public class MyServlet extends HttpServlet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
|
resp.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
resp.getWriter().write("test");
|
||||||
|
resp.getWriter().flush();
|
||||||
|
resp.getWriter().close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Context;
|
||||||
|
import org.apache.catalina.LifecycleException;
|
||||||
|
import org.apache.catalina.startup.Tomcat;
|
||||||
|
import org.apache.tomcat.util.descriptor.web.FilterDef;
|
||||||
|
import org.apache.tomcat.util.descriptor.web.FilterMap;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 1/10/18.
|
||||||
|
*/
|
||||||
|
public class ProgrammaticTomcat {
|
||||||
|
|
||||||
|
private Tomcat tomcat = null;
|
||||||
|
|
||||||
|
//uncomment for live test
|
||||||
|
// public static void main(String[] args) throws LifecycleException, ServletException, URISyntaxException, IOException {
|
||||||
|
// startTomcat();
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void startTomcat() throws LifecycleException {
|
||||||
|
tomcat = new Tomcat();
|
||||||
|
tomcat.setPort(8080);
|
||||||
|
tomcat.setHostname("localhost");
|
||||||
|
String appBase = ".";
|
||||||
|
tomcat
|
||||||
|
.getHost()
|
||||||
|
.setAppBase(appBase);
|
||||||
|
|
||||||
|
File docBase = new File(System.getProperty("java.io.tmpdir"));
|
||||||
|
Context context = tomcat.addContext("", docBase.getAbsolutePath());
|
||||||
|
|
||||||
|
//add a servlet
|
||||||
|
Class servletClass = MyServlet.class;
|
||||||
|
Tomcat.addServlet(context, servletClass.getSimpleName(), servletClass.getName());
|
||||||
|
context.addServletMappingDecoded("/my-servlet/*", servletClass.getSimpleName());
|
||||||
|
|
||||||
|
//add a filter and filterMapping
|
||||||
|
Class filterClass = MyFilter.class;
|
||||||
|
FilterDef myFilterDef = new FilterDef();
|
||||||
|
myFilterDef.setFilterClass(filterClass.getName());
|
||||||
|
myFilterDef.setFilterName(filterClass.getSimpleName());
|
||||||
|
context.addFilterDef(myFilterDef);
|
||||||
|
|
||||||
|
FilterMap myFilterMap = new FilterMap();
|
||||||
|
myFilterMap.setFilterName(filterClass.getSimpleName());
|
||||||
|
myFilterMap.addURLPattern("/my-servlet/*");
|
||||||
|
context.addFilterMap(myFilterMap);
|
||||||
|
|
||||||
|
tomcat.start();
|
||||||
|
//uncomment for live test
|
||||||
|
// tomcat
|
||||||
|
// .getServer()
|
||||||
|
// .await();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopTomcat() throws LifecycleException {
|
||||||
|
tomcat.stop();
|
||||||
|
tomcat.destroy();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.baeldung.tomcat;
|
||||||
|
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||||
|
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by adi on 1/14/18.
|
||||||
|
*/
|
||||||
|
@RunWith(BlockJUnit4ClassRunner.class)
|
||||||
|
public class ProgrammaticTomcatTest {
|
||||||
|
|
||||||
|
private ProgrammaticTomcat tomcat = new ProgrammaticTomcat();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
tomcat.startTomcat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
tomcat.stopTomcat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTomcatStarted_whenAccessServlet_responseIsTestAndResponseHeaderIsSet() throws Exception {
|
||||||
|
CloseableHttpClient httpClient = HttpClientBuilder
|
||||||
|
.create()
|
||||||
|
.build();
|
||||||
|
HttpGet getServlet = new HttpGet("http://localhost:8080/my-servlet");
|
||||||
|
|
||||||
|
HttpResponse response = httpClient.execute(getServlet);
|
||||||
|
assertEquals(HttpStatus.SC_OK, response
|
||||||
|
.getStatusLine()
|
||||||
|
.getStatusCode());
|
||||||
|
|
||||||
|
String myHeaderValue = response
|
||||||
|
.getFirstHeader("myHeader")
|
||||||
|
.getValue();
|
||||||
|
assertEquals("myHeaderValue", myHeaderValue);
|
||||||
|
|
||||||
|
HttpEntity responseEntity = response.getEntity();
|
||||||
|
assertNotNull(responseEntity);
|
||||||
|
|
||||||
|
String responseString = EntityUtils.toString(responseEntity, "UTF-8");
|
||||||
|
assertEquals("test", responseString);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,3 +4,4 @@
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [Creating a Custom Logback Appender](http://www.baeldung.com/custom-logback-appender)
|
- [Creating a Custom Logback Appender](http://www.baeldung.com/custom-logback-appender)
|
||||||
|
- [Get Log Output in JSON Format](http://www.baeldung.com/java-log-json-output)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
### Relevant articles
|
### Relevant articles
|
||||||
|
|
||||||
- [Simple Jenkins Pipeline with Marathon and Mesos](http://www.baeldung.com/jenkins-pipeline-with-marathon-mesos)
|
- [Simple Jenkins Pipeline with Marathon and Mesos](http://www.baeldung.com/jenkins-pipeline-with-marathon-mesos)
|
||||||
|
|
||||||
|
To run the pipeline, please modify the dockerise.sh file with your own useranema and password for docker login.
|
||||||
|
|
1
pom.xml
1
pom.xml
|
@ -93,6 +93,7 @@
|
||||||
<module>javax-servlets</module>
|
<module>javax-servlets</module>
|
||||||
<module>javaxval</module>
|
<module>javaxval</module>
|
||||||
<module>jaxb</module>
|
<module>jaxb</module>
|
||||||
|
<module>jgroups</module>
|
||||||
<module>jee-7</module>
|
<module>jee-7</module>
|
||||||
<!-- <module>jhipster/jhipster-monolithic</module> -->
|
<!-- <module>jhipster/jhipster-monolithic</module> -->
|
||||||
<module>jjwt</module>
|
<module>jjwt</module>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# About this project
|
||||||
|
This project contains examples from the [Spring Data with Spring Security](http://www.baeldung.com/spring-data-with-spring-security) article from Baeldung.
|
||||||
|
|
||||||
|
# Running the project
|
||||||
|
The application uses [Spring Boot](http://projects.spring.io/spring-boot/), so it is easy to run. You can start it any of a few ways:
|
||||||
|
* Run the `main` method from `SpringDataRestApplication`
|
||||||
|
* Use the Maven Spring Boot plugin: `mvn spring-boot:run`
|
||||||
|
* Package the application as a JAR and run it using `java -jar spring-data-spring-security.jar`
|
||||||
|
|
||||||
|
# Viewing the running application
|
||||||
|
To view the running application, visit [http://localhost:8080](http://localhost:8080) in your browser
|
||||||
|
|
||||||
|
###Relevant Articles:
|
||||||
|
- [Spring Data with Spring Security](http://www.baeldung.com/spring-data-with-spring-security)
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>spring-data-spring-security</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>intro-spring-data-spring-security</name>
|
||||||
|
<description>Spring Data with Spring Security</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-boot-5</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-boot-5</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-data</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-jasper</artifactId>
|
||||||
|
<!-- <scope>provided</scope> -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>jstl</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||||
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
|
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@PropertySource("classpath:persistence-h2.properties")
|
||||||
|
@EnableJpaRepositories(basePackages = { "com.baeldung.data.repositories" })
|
||||||
|
@EnableWebMvc
|
||||||
|
@Import(SpringSecurityConfig.class)
|
||||||
|
public class AppConfig extends WebMvcConfigurerAdapter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Environment env;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSource dataSource() {
|
||||||
|
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||||
|
dataSource.setDriverClassName(env.getProperty("driverClassName"));
|
||||||
|
dataSource.setUrl(env.getProperty("url"));
|
||||||
|
dataSource.setUsername(env.getProperty("user"));
|
||||||
|
dataSource.setPassword(env.getProperty("password"));
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||||
|
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||||
|
em.setDataSource(dataSource());
|
||||||
|
em.setPackagesToScan(new String[] { "com.baeldung.models" });
|
||||||
|
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||||
|
em.setJpaProperties(additionalProperties());
|
||||||
|
return em;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Properties additionalProperties() {
|
||||||
|
final Properties hibernateProperties = new Properties();
|
||||||
|
if (env.getProperty("hibernate.hbm2ddl.auto") != null) {
|
||||||
|
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
||||||
|
}
|
||||||
|
if (env.getProperty("hibernate.dialect") != null) {
|
||||||
|
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
||||||
|
}
|
||||||
|
if (env.getProperty("hibernate.show_sql") != null) {
|
||||||
|
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
|
||||||
|
}
|
||||||
|
return hibernateProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
import com.baeldung.security.AuthenticationSuccessHandlerImpl;
|
||||||
|
import com.baeldung.security.CustomUserDetailsService;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
@ComponentScan("com.baeldung.security")
|
||||||
|
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebApplicationContext applicationContext;
|
||||||
|
private CustomUserDetailsService userDetailsService;
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationSuccessHandlerImpl successHandler;
|
||||||
|
@Autowired
|
||||||
|
private DataSource dataSource;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void completeSetup() {
|
||||||
|
userDetailsService = applicationContext.getBean(CustomUserDetailsService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
auth.userDetailsService(userDetailsService)
|
||||||
|
.passwordEncoder(encoder())
|
||||||
|
.and()
|
||||||
|
.authenticationProvider(authenticationProvider())
|
||||||
|
.jdbcAuthentication()
|
||||||
|
.dataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(WebSecurity web) throws Exception {
|
||||||
|
web.ignoring()
|
||||||
|
.antMatchers("/resources/**");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(final HttpSecurity http) throws Exception {
|
||||||
|
http.authorizeRequests()
|
||||||
|
.antMatchers("/login")
|
||||||
|
.permitAll()
|
||||||
|
.and()
|
||||||
|
.formLogin()
|
||||||
|
.permitAll()
|
||||||
|
.successHandler(successHandler)
|
||||||
|
.and()
|
||||||
|
.csrf()
|
||||||
|
.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DaoAuthenticationProvider authenticationProvider() {
|
||||||
|
final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||||
|
authProvider.setUserDetailsService(userDetailsService);
|
||||||
|
authProvider.setPasswordEncoder(encoder());
|
||||||
|
return authProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder encoder() {
|
||||||
|
return new BCryptPasswordEncoder(11);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
|
||||||
|
return new SecurityEvaluationContextExtension();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.data.repositories;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||||
|
|
||||||
|
import com.baeldung.models.Tweet;
|
||||||
|
|
||||||
|
public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> {
|
||||||
|
|
||||||
|
@Query("select twt from Tweet twt JOIN twt.likes as lk where lk = ?#{ principal?.username } or twt.owner = ?#{ principal?.username }")
|
||||||
|
Page<Tweet> getMyTweetsAndTheOnesILiked(Pageable pageable);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.data.repositories;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.baeldung.models.AppUser;
|
||||||
|
import com.baeldung.models.Tweet;
|
||||||
|
|
||||||
|
public interface UserRepository extends CrudRepository<AppUser, Long> {
|
||||||
|
AppUser findByUsername(String username);
|
||||||
|
|
||||||
|
List<AppUser> findByName(String name);
|
||||||
|
|
||||||
|
@Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE u.username = ?#{ principal?.username }")
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
public void updateLastLogin(@Param("lastLogin") Date lastLogin);
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.baeldung.models;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
public class AppUser {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
@Column(unique = true)
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private boolean enabled = true;
|
||||||
|
private Date lastLogin;
|
||||||
|
|
||||||
|
private AppUser() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppUser(String name, String email, String password) {
|
||||||
|
this.username = email;
|
||||||
|
this.name = name;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastLogin() {
|
||||||
|
return lastLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastLogin(Date lastLogin) {
|
||||||
|
this.lastLogin = lastLogin;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.models;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Tweet {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private long id;
|
||||||
|
private String tweet;
|
||||||
|
private String owner;
|
||||||
|
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
|
||||||
|
private Set<String> likes = new HashSet();
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tweet() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tweet(String tweet, String owner) {
|
||||||
|
this.tweet = tweet;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTweet() {
|
||||||
|
return tweet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTweet(String tweet) {
|
||||||
|
this.tweet = tweet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(String owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getLikes() {
|
||||||
|
return likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikes(Set<String> likes) {
|
||||||
|
this.likes = likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.baeldung.security;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import com.baeldung.models.AppUser;
|
||||||
|
|
||||||
|
public class AppUserPrincipal implements UserDetails {
|
||||||
|
|
||||||
|
private final AppUser user;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
public AppUserPrincipal(AppUser user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return user.getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return user.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
final List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("User"));
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
public AppUser getAppUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.security;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.baeldung.data.repositories.UserRepository;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) throws IOException, ServletException {
|
||||||
|
userRepository.updateLastLogin(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.security;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
|
import com.baeldung.data.repositories.UserRepository;
|
||||||
|
import com.baeldung.models.AppUser;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CustomUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebApplicationContext applicationContext;
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
public CustomUserDetailsService() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void completeSetup() {
|
||||||
|
userRepository = applicationContext.getBean(UserRepository.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(final String username) {
|
||||||
|
final AppUser appUser = userRepository.findByUsername(username);
|
||||||
|
if (appUser == null) {
|
||||||
|
throw new UsernameNotFoundException(username);
|
||||||
|
}
|
||||||
|
return new AppUserPrincipal(appUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
|
import com.baeldung.models.AppUser;
|
||||||
|
import com.baeldung.models.Tweet;
|
||||||
|
|
||||||
|
public class DummyContentUtil {
|
||||||
|
|
||||||
|
public static final List<AppUser> generateDummyUsers() {
|
||||||
|
List<AppUser> appUsers = new ArrayList<>();
|
||||||
|
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
appUsers.add(new AppUser("Lionel Messi", "lionel@messi.com", passwordEncoder.encode("li1234")));
|
||||||
|
appUsers.add(new AppUser("Cristiano Ronaldo", "cristiano@ronaldo.com", passwordEncoder.encode("c1234")));
|
||||||
|
appUsers.add(new AppUser("Neymar Dos Santos", "neymar@neymar.com", passwordEncoder.encode("n1234")));
|
||||||
|
appUsers.add(new AppUser("Luiz Suarez", "luiz@suarez.com", passwordEncoder.encode("lu1234")));
|
||||||
|
appUsers.add(new AppUser("Andres Iniesta", "andres@iniesta.com", passwordEncoder.encode("a1234")));
|
||||||
|
appUsers.add(new AppUser("Ivan Rakitic", "ivan@rakitic.com", passwordEncoder.encode("i1234")));
|
||||||
|
appUsers.add(new AppUser("Ousman Dembele", "ousman@dembele.com", passwordEncoder.encode("o1234")));
|
||||||
|
appUsers.add(new AppUser("Sergio Busquet", "sergio@busquet.com", passwordEncoder.encode("s1234")));
|
||||||
|
appUsers.add(new AppUser("Gerard Pique", "gerard@pique.com", passwordEncoder.encode("g1234")));
|
||||||
|
appUsers.add(new AppUser("Ter Stergen", "ter@stergen.com", passwordEncoder.encode("t1234")));
|
||||||
|
return appUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final List<Tweet> generateDummyTweets(List<AppUser> users) {
|
||||||
|
List<Tweet> tweets = new ArrayList<>();
|
||||||
|
Random random = new Random();
|
||||||
|
IntStream.range(0, 9)
|
||||||
|
.sequential()
|
||||||
|
.forEach(i -> {
|
||||||
|
Tweet twt = new Tweet(String.format("Tweet %d", i), users.get(random.nextInt(users.size()))
|
||||||
|
.getUsername());
|
||||||
|
twt.getLikes()
|
||||||
|
.addAll(users.subList(0, random.nextInt(users.size()))
|
||||||
|
.stream()
|
||||||
|
.map(AppUser::getUsername)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
tweets.add(twt);
|
||||||
|
});
|
||||||
|
return tweets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<GrantedAuthority> getAuthorities() {
|
||||||
|
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
|
||||||
|
GrantedAuthority grantedAuthority = new GrantedAuthority() {
|
||||||
|
public String getAuthority() {
|
||||||
|
return "ROLE_USER";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
grantedAuthorities.add(grantedAuthority);
|
||||||
|
return grantedAuthorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
driverClassName=org.h2.Driver
|
||||||
|
url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1
|
||||||
|
username=sa
|
||||||
|
password=
|
||||||
|
|
||||||
|
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||||
|
hibernate.show_sql=false
|
||||||
|
hibernate.hbm2ddl.auto=create-drop
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.baeldung.relationships;
|
||||||
|
|
||||||
|
import static org.springframework.util.Assert.isTrue;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
|
import com.baeldung.AppConfig;
|
||||||
|
import com.baeldung.data.repositories.TweetRepository;
|
||||||
|
import com.baeldung.data.repositories.UserRepository;
|
||||||
|
import com.baeldung.models.AppUser;
|
||||||
|
import com.baeldung.models.Tweet;
|
||||||
|
import com.baeldung.security.AppUserPrincipal;
|
||||||
|
import com.baeldung.util.DummyContentUtil;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@WebAppConfiguration
|
||||||
|
@ContextConfiguration
|
||||||
|
@DirtiesContext
|
||||||
|
public class SpringDataWithSecurityTest {
|
||||||
|
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||||
|
@Autowired
|
||||||
|
private ServletContext servletContext;
|
||||||
|
private static UserRepository userRepository;
|
||||||
|
private static TweetRepository tweetRepository;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void testInit() {
|
||||||
|
ctx.register(AppConfig.class);
|
||||||
|
ctx.setServletContext(servletContext);
|
||||||
|
ctx.refresh();
|
||||||
|
userRepository = ctx.getBean(UserRepository.class);
|
||||||
|
tweetRepository = ctx.getBean(TweetRepository.class);
|
||||||
|
List<AppUser> appUsers = (List<AppUser>) userRepository.save(DummyContentUtil.generateDummyUsers());
|
||||||
|
tweetRepository.save(DummyContentUtil.generateDummyTweets(appUsers));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDown() {
|
||||||
|
tweetRepository.deleteAll();
|
||||||
|
userRepository.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAppUser_whenLoginSuccessful_shouldUpdateLastLogin() {
|
||||||
|
AppUser appUser = userRepository.findByUsername("lionel@messi.com");
|
||||||
|
Authentication auth = new UsernamePasswordAuthenticationToken(new AppUserPrincipal(appUser), null, DummyContentUtil.getAuthorities());
|
||||||
|
SecurityContextHolder.getContext()
|
||||||
|
.setAuthentication(auth);
|
||||||
|
userRepository.updateLastLogin(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||||
|
public void givenNoAppUserInSecurityContext_whenUpdateLastLoginAttempted_shouldFail() {
|
||||||
|
userRepository.updateLastLogin(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAppUser_whenLoginSuccessful_shouldReadMyPagedTweets() {
|
||||||
|
AppUser appUser = userRepository.findByUsername("lionel@messi.com");
|
||||||
|
Authentication auth = new UsernamePasswordAuthenticationToken(new AppUserPrincipal(appUser), null, DummyContentUtil.getAuthorities());
|
||||||
|
SecurityContextHolder.getContext()
|
||||||
|
.setAuthentication(auth);
|
||||||
|
Page<Tweet> page = null;
|
||||||
|
do {
|
||||||
|
page = tweetRepository.getMyTweetsAndTheOnesILiked(new PageRequest(page != null ? page.getNumber() + 1 : 0, 5));
|
||||||
|
for (Tweet twt : page.getContent()) {
|
||||||
|
isTrue((twt.getOwner() == appUser.getUsername()) || (twt.getLikes()
|
||||||
|
.contains(appUser.getUsername())), "I do not have any Tweets");
|
||||||
|
}
|
||||||
|
} while (page.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||||
|
public void givenNoAppUser_whenPaginatedResultsRetrievalAttempted_shouldFail() {
|
||||||
|
Page<Tweet> page = null;
|
||||||
|
do {
|
||||||
|
page = tweetRepository.getMyTweetsAndTheOnesILiked(new PageRequest(page != null ? page.getNumber() + 1 : 0, 5));
|
||||||
|
} while (page != null && page.hasNext());
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,3 +17,4 @@
|
||||||
- [Introduction to Jukito](http://www.baeldung.com/jukito)
|
- [Introduction to Jukito](http://www.baeldung.com/jukito)
|
||||||
- [Custom JUnit 4 Test Runners](http://www.baeldung.com/junit-4-custom-runners)
|
- [Custom JUnit 4 Test Runners](http://www.baeldung.com/junit-4-custom-runners)
|
||||||
- [Guide to JSpec](http://www.baeldung.com/jspec)
|
- [Guide to JSpec](http://www.baeldung.com/jspec)
|
||||||
|
- [Custom Assertions with AssertJ](http://www.baeldung.com/assertj-custom-assertion)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.testing.assertj;
|
||||||
|
|
||||||
|
public class Member {
|
||||||
|
private String name;
|
||||||
|
private int age;
|
||||||
|
|
||||||
|
public Member(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.baeldung.testing.assertj;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.allOf;
|
||||||
|
import static org.assertj.core.api.Assertions.anyOf;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.not;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.assertj.core.api.Condition;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class AssertJConditionUnitTest {
|
||||||
|
private Condition<Member> senior = new Condition<>(m -> m.getAge() >= 60, "senior");
|
||||||
|
private Condition<Member> nameJohn = new Condition<>(m -> m.getName().equalsIgnoreCase("John"), "name John");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingMemberAgeCondition_thenCorrect() {
|
||||||
|
Member member = new Member("John", 65);
|
||||||
|
assertThat(member).is(senior);
|
||||||
|
|
||||||
|
try {
|
||||||
|
assertThat(member).isNot(senior);
|
||||||
|
fail();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
assertThat(e).hasMessageContaining("not to be <senior>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingMemberNameCondition_thenCorrect() {
|
||||||
|
Member member = new Member("Jane", 60);
|
||||||
|
assertThat(member).doesNotHave(nameJohn);
|
||||||
|
|
||||||
|
try {
|
||||||
|
assertThat(member).has(nameJohn);
|
||||||
|
fail();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
assertThat(e).hasMessageContaining("to have:\n <name John>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCollectionConditionsAreSatisfied_thenCorrect() {
|
||||||
|
List<Member> members = new ArrayList<>();
|
||||||
|
members.add(new Member("Alice", 50));
|
||||||
|
members.add(new Member("Bob", 60));
|
||||||
|
|
||||||
|
assertThat(members).haveExactly(1, senior);
|
||||||
|
assertThat(members).doNotHave(nameJohn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCombiningAllOfConditions_thenCorrect() {
|
||||||
|
Member john = new Member("John", 60);
|
||||||
|
Member jane = new Member("Jane", 50);
|
||||||
|
|
||||||
|
assertThat(john).is(allOf(senior, nameJohn));
|
||||||
|
assertThat(jane).is(allOf(not(nameJohn), not(senior)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCombiningAnyOfConditions_thenCorrect() {
|
||||||
|
Member john = new Member("John", 50);
|
||||||
|
Member jane = new Member("Jane", 60);
|
||||||
|
|
||||||
|
assertThat(john).is(anyOf(senior, nameJohn));
|
||||||
|
assertThat(jane).is(anyOf(nameJohn, senior));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue