This commit is contained in:
Jonathan Cook 2020-11-13 16:45:25 +01:00
commit 080122250b
57 changed files with 1159 additions and 130 deletions

View File

@ -10,3 +10,4 @@ This module contains articles about Java 10 core features
- [Deep Dive Into the New Java JIT Compiler Graal](https://www.baeldung.com/graal-java-jit-compiler)
- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets)
- [Converting between a List and a Set in Java](https://www.baeldung.com/convert-list-to-set-and-set-to-list)
- [Java IndexOutOfBoundsException “Source Does Not Fit in Dest”](https://www.baeldung.com/java-indexoutofboundsexception)

View File

@ -4,3 +4,5 @@
- [IllegalArgumentException or NullPointerException for a Null Parameter?](https://www.baeldung.com/java-illegalargumentexception-or-nullpointerexception)
- [IllegalMonitorStateException in Java](https://www.baeldung.com/java-illegalmonitorstateexception)
- [AbstractMethodError in Java](https://www.baeldung.com/java-abstractmethoderror)
- [Java IndexOutOfBoundsException “Source Does Not Fit in Dest”](https://www.baeldung.com/java-indexoutofboundsexception)
- [Localizing Exception Messages in Java](https://www.baeldung.com/java-localize-exception-messages)

View File

@ -0,0 +1,14 @@
package com.baeldung.exception.indexoutofbounds;
import java.util.ArrayList;
import java.util.List;
public class CopyListUsingAddAllMethodDemo {
static List<Integer> copyList(List<Integer> source) {
List<Integer> destination = new ArrayList<>();
destination.addAll(source);
return destination;
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.exception.indexoutofbounds;
import java.util.Collections;
import java.util.List;
public class CopyListUsingCollectionsCopyMethodDemo {
static void copyList(List<Integer> source, List<Integer> destination) {
Collections.copy(destination, source);
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.exception.indexoutofbounds;
import java.util.ArrayList;
import java.util.List;
public class CopyListUsingConstructorDemo {
static List<Integer> copyList(List<Integer> source) {
return new ArrayList<>(source);
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.exception.indexoutofbounds;
import java.util.List;
import java.util.stream.Collectors;
public class CopyListUsingJava8StreamDemo {
static List<Integer> copyList(List<Integer> source) {
return source
.stream()
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.exception.indexoutofbounds;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class IndexOutOfBoundsExceptionDemo {
static List<Integer> copyList(List<Integer> source) {
List<Integer> destination = new ArrayList<>(source.size());
Collections.copy(destination, source);
return destination;
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.exceptions.localization;
import java.util.Locale;
public class LocalizedException extends Exception {
private static final long serialVersionUID = 1L;
private final String messageKey;
private final Locale locale;
public LocalizedException(String messageKey) {
this(messageKey, Locale.getDefault());
}
public LocalizedException(String messageKey, Locale locale) {
this.messageKey = messageKey;
this.locale = locale;
}
/**
* @return a localized message based on the messageKey provided at instantiation.
*/
public String getMessage() {
/*
* This is a deliberate role reversal of the default implementation of getLocalizedMessage.
* some logging frameworks like Log4J 1 & 2 and Logback will use getMessage instead of
* getLocalizedMessage when logging Throwables. If we want to use these frameworks in client
* applications to log localized messages, then we'll need to override getMessage in a
* similar fashion to return the appropriate content. Or, you can call getLocalizedMessage
* on your own to create the log content.
*/
return getLocalizedMessage();
}
/**
* @return a localized message based on the messageKey provided at instantiation.
*/
public String getLocalizedMessage() {
/*
* java.util.logging uses getLocalizedMessage when logging Throwables.
*/
return Messages.getMessageForLocale(messageKey, locale);
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.exceptions.localization;
import java.util.Locale;
import java.util.ResourceBundle;
public class Messages {
/**
* Retrieves the value for the messageKey from the locale-specific messages.properties, or from
* the base messages.properties for unsupported locales.
*
* @param messageKey The key for the message in the messages.properties ResourceBundle.
* @param locale The locale to search the message key.
* @return The value defined for the messageKey in the provided locale.
*/
public static String getMessageForLocale(String messageKey, Locale locale) {
/*
* For more complex implementations, you will want a var-args parameter for MessageFormat
* substitutions. Then we can read the value from the bundle and pass the value with the
* substitutions to MessageFormat to create the final message value.
*/
return ResourceBundle.getBundle("messages", locale)
.getString(messageKey);
}
}

View File

@ -0,0 +1 @@
message.exception = I am an exception.

View File

@ -0,0 +1 @@
message.exception = Je suis une exception.

View File

@ -0,0 +1,18 @@
package com.baeldung.exception.indexoutofbounds;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class CopyListUsingAddAllMethodDemoUnitTest {
@Test
void whenPassValidArrayList_thenCopyListUsingAddAllMethod() {
List<Integer> source = Arrays.asList(11, 22, 33);
assertEquals(source, CopyListUsingAddAllMethodDemo.copyList(source));
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.exception.indexoutofbounds;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
public class CopyListUsingCollectionsCopyMethodDemoUnitTest {
@Test
void whenCopyListUsingCollectionsCopy_thenOverrideAllDestinationListValues() {
List<Integer> source = Arrays.asList(11, 22, 33);
List<Integer> destination = Arrays.asList(1, 2, 3);
CopyListUsingCollectionsCopyMethodDemo.copyList(source, destination);
assertEquals(source, destination);
}
@Test
void whenCopyListUsingCollectionsCopy_thenOverrideInitialDestinationValuesAndOthersShouldBeUnchanged(){
List<Integer> source = Arrays.asList(11, 22, 33);
List<Integer> destination = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> expectedList = Arrays.asList(11, 22, 33, 4, 5);
CopyListUsingCollectionsCopyMethodDemo.copyList(source, destination);
assertEquals(expectedList, destination);
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.exception.indexoutofbounds;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class CopyListUsingConstructorDemoUnitTest {
@Test
void whenCopyListUsingConstructor_thenMakeACopyOfList() {
List<Integer> source = Arrays.asList(11, 22, 33);
assertEquals(source, CopyListUsingConstructorDemo.copyList(source));
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.exception.indexoutofbounds;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class CopyListUsingJava8StreamDemoUnitTest {
@Test
void whenCopyListUsingStream_thenMakeACopyOfArrayList() {
List<Integer> source = Arrays.asList(11, 22, 33);
assertEquals(source, CopyListUsingJava8StreamDemo.copyList(source));
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.exception.indexoutofbounds;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class IndexOutOfBoundsExceptionDemoUnitTest {
@Test
void givenDestinationArrayListSizeIsZero_whenCopySourceArrayListToDestination_thenShouldThrowIndexOutOfBoundsException() {
List<Integer> source = Arrays.asList(1, 2, 3, 4, 5);
assertThrows(IndexOutOfBoundsException.class, () -> IndexOutOfBoundsExceptionDemo.copyList(source));
}
@Test
void givenSourceAndDestinationListSizeIsEqual_whenCopySourceArrayListToDestination_thenShouldNotThrowIndexOutOfBoundsException() {
List<Integer> source = Collections.emptyList();
assertEquals(source, IndexOutOfBoundsExceptionDemo.copyList(source));
}
}

View File

@ -0,0 +1,61 @@
package com.baeldung.exceptions.localization;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
public class LocalizedExceptionUnitTest {
private Locale originalDefaultLocale;
@Before
public void saveOriginalDefaultLocale() {
originalDefaultLocale = Locale.getDefault();
}
@After
public void restoreOriginalDefaultLocale() {
Locale.setDefault(originalDefaultLocale);
}
@Test
public void givenUsEnglishDefaultLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessages() {
Locale.setDefault(Locale.US);
LocalizedException localizedException = new LocalizedException("message.exception");
String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage();
assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception.");
}
@Test
public void givenFranceFrenchDefaultLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() {
Locale.setDefault(Locale.FRANCE);
LocalizedException localizedException = new LocalizedException("message.exception");
String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage();
assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception.");
}
@Test
public void givenUsEnglishProvidedLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessage() {
LocalizedException localizedException = new LocalizedException("message.exception", Locale.US);
String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage();
assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception.");
}
@Test
public void givenFranceFrenchProvidedLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() {
LocalizedException localizedException = new LocalizedException("message.exception", Locale.FRANCE);
String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage();
assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception.");
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.exceptions.localization;
import org.junit.Test;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
public class MessagesUnitTest {
@Test
public void givenUsEnglishLocale_whenRetrievingMessage_thenEnglishTranslationIsReturned() {
String translatedMessage = Messages.getMessageForLocale("message.exception", Locale.US);
assertThat(translatedMessage).isEqualTo("I am an exception.");
}
@Test
public void givenFranceFrenchLocale_whenRetrievingMessage_thenFrenchTranslationIsReturned() {
String translatedMessage = Messages.getMessageForLocale("message.exception", Locale.FRANCE);
assertThat(translatedMessage).isEqualTo("Je suis une exception.");
}
}

View File

@ -1 +1,3 @@
## Relevant articles:
- [Functional Programming in Java](https://www.baeldung.com/java-functional-programming)

View File

@ -8,4 +8,5 @@ This module contains articles about core features in the Java language
- [Checking if a Class Exists in Java](https://www.baeldung.com/java-check-class-exists)
- [The Difference Between a.getClass() and A.class in Java](https://www.baeldung.com/java-getclass-vs-class)
- [Constants in Java: Patterns and Anti-Patterns](https://www.baeldung.com/java-constants-good-practices)
- [The transient Keyword in Java](https://www.baeldung.com/java-transient-keyword)
- [[<-- Prev]](/core-java-modules/core-java-lang-2)

View File

@ -12,3 +12,4 @@ This module contains articles about types in Java
- [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values)
- [A Guide to Java Enums](https://www.baeldung.com/a-guide-to-java-enums)
- [Determine if an Object is of Primitive Type](https://www.baeldung.com/java-object-primitive-type)
- [Extending Enums in Java](https://www.baeldung.com/java-extending-enums)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Version Comparison in Java](https://www.baeldung.com/java-comparing-versions)
- [Java (String) or .toString()?](https://www.baeldung.com/java-string-casting-vs-tostring)

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.channels.Channel

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.channels.Channel

View File

@ -1,6 +1,6 @@
package com.baeldung.channles
package com.baeldung.channels
import com.baeldung.channles.OrderStatus.*
import com.baeldung.channels.OrderStatus.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.produce

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.channels.Channel

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.ReceiveChannel

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.channels.ticker
import kotlinx.coroutines.delay

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.channels.Channel

View File

@ -1,4 +1,4 @@
package com.baeldung.channles
package com.baeldung.channels
import java.text.SimpleDateFormat
import java.util.*

33
discord4j/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
README.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

63
discord4j/pom.xml Normal file
View File

@ -0,0 +1,63 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.baeldung</groupId>
<artifactId>discord4j-bot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>discord4j-bot</name>
<description>Demo Discord bot using Discord4J + Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.discord4j</groupId>
<artifactId>discord4j-core</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,48 @@
package com.baeldung.discordbot;
import com.baeldung.discordbot.events.EventListener;
import discord4j.core.DiscordClientBuilder;
import discord4j.core.GatewayDiscordClient;
import discord4j.core.event.domain.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class BotConfiguration {
private static final Logger log = LoggerFactory.getLogger( BotConfiguration.class );
@Value("${token}")
private String token;
@Bean
public <T extends Event> GatewayDiscordClient gatewayDiscordClient(List<EventListener<T>> eventListeners) {
GatewayDiscordClient client = null;
try {
client = DiscordClientBuilder.create(token)
.build()
.login()
.block();
for(EventListener<T> listener : eventListeners) {
client.on(listener.getEventType())
.flatMap(listener::execute)
.onErrorResume(listener::handleError)
.subscribe();
}
client.onDisconnect().block();
}
catch ( Exception exception ) {
log.error( "Be sure to use a valid bot token!", exception );
}
return client;
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.discordbot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DiscordBotApplication {
public static void main(String[] args) {
SpringApplication.run(DiscordBotApplication.class, args);
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.discordbot.events;
import discord4j.core.event.domain.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
public interface EventListener<T extends Event> {
Logger LOG = LoggerFactory.getLogger(EventListener.class);
Class<T> getEventType();
Mono<Void> execute(T event);
default Mono<Void> handleError(Throwable error) {
LOG.error("Unable to process " + getEventType().getSimpleName(), error);
return Mono.empty();
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.discordbot.events;
import discord4j.core.event.domain.message.MessageCreateEvent;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
public class MessageCreateListener extends MessageListener implements EventListener<MessageCreateEvent> {
@Override
public Class<MessageCreateEvent> getEventType() {
return MessageCreateEvent.class;
}
@Override
public Mono<Void> execute(MessageCreateEvent event) {
return processCommand(event.getMessage());
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.discordbot.events;
import discord4j.core.object.entity.Message;
import reactor.core.publisher.Mono;
public abstract class MessageListener {
public Mono<Void> processCommand(Message eventMessage) {
return Mono.just(eventMessage)
.filter(message -> message.getAuthor().map(user -> !user.isBot()).orElse(false))
.filter(message -> message.getContent().equalsIgnoreCase("!todo"))
.flatMap(Message::getChannel)
.flatMap(channel -> channel.createMessage("Things to do today:\n" +
" - write a bot\n" +
" - eat lunch\n" +
" - play a game"))
.then();
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.discordbot.events;
import discord4j.core.event.domain.message.MessageUpdateEvent;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
public class MessageUpdateListener extends MessageListener implements EventListener<MessageUpdateEvent> {
@Override
public Class<MessageUpdateEvent> getEventType() {
return MessageUpdateEvent.class;
}
@Override
public Mono<Void> execute(MessageUpdateEvent event) {
return Mono.just(event)
.filter(MessageUpdateEvent::isContentChanged)
.flatMap(MessageUpdateEvent::getMessage)
.flatMap(super::processCommand);
}
}

View File

@ -0,0 +1 @@
token: 'our-token-here'

View File

@ -0,0 +1,12 @@
package com.baeldung.discordbot;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class DiscordBotLiveTest {
@Test
public void contextTest() {
}
}

View File

@ -6,3 +6,4 @@ This module contains articles about the Java Native Interface (JNI).
- [Guide to JNI (Java Native Interface)](https://www.baeldung.com/jni)
- [Using JNA to Access Native Dynamic Libraries](https://www.baeldung.com/java-jna-dynamic-libraries)
- [Check if a Java Program Is Running in 64-Bit or 32-Bit JVM](https://www.baeldung.com/java-detect-jvm-64-or-32-bit)

View File

@ -5,3 +5,4 @@ This module contains articles about the Java Persistence API (JPA) in Java.
### Relevant Articles:
- [JPA Entity Equality](https://www.baeldung.com/jpa-entity-equality)
- [Ignoring Fields With the JPA @Transient Annotation](https://www.baeldung.com/jpa-transient-ignore-field)

View File

@ -27,7 +27,21 @@
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.9.8</version>
</dependency>
<!--Compile time JPA API -->
<dependency>
<groupId>javax.persistence</groupId>

View File

@ -0,0 +1,37 @@
package com.baeldung.ignorable.fields;
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
public class HibernateConfig {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
Configuration configuration = new Configuration();
Properties settings = new Properties();
settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
settings.put(Environment.URL, "jdbc:mysql://localhost:3306/app_db?useSSL=false");
settings.put(Environment.USER, "root");
settings.put(Environment.PASS, "password");
settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
configuration.setProperties(settings);
configuration.addAnnotatedClass(User.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
return sessionFactory;
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.ignorable.fields;
import java.io.Serializable;
import java.util.StringJoiner;
import javax.persistence.*;
@Entity
@Table(name = "Users")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String email;
private String password;
@Transient
private String currentDevice;
// Needed for Hibernate mapping
public User() {
}
public User(String email, String password, String currentDevice) {
this.email = email;
this.password = password;
this.currentDevice = currentDevice;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCurrentDevice() {
return currentDevice;
}
public void setCurrentDevice(String currentDevice) {
this.currentDevice = currentDevice;
}
@Override
public String toString() {
return new StringJoiner(", ", User.class.getSimpleName() + "[", "]").add("id=" + id)
.add("email='" + email + "'")
.add("password='" + password + "'")
.add("currentDevice='" + currentDevice + "'")
.toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof User))
return false;
User user = (User) o;
return email.equals(user.email);
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.ignorable.fields;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class UserDao {
public void saveUser(User user) {
Transaction transaction = null;
try (Session session = HibernateConfig.getSessionFactory().openSession()) {
transaction = session.beginTransaction();
session.save(user);
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
}
}
public List<User> getUsers() {
try (Session session = HibernateConfig.getSessionFactory().openSession()) {
return session.createQuery("from User", User.class).list();
}
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.jpa.removal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import java.util.Objects;
@Entity
public class LineItem {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne
private OrderRequest orderRequest;
public LineItem(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
LineItem lineItem = (LineItem) o;
return Objects.equals(id, lineItem.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
protected LineItem() {
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.jpa.removal;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import java.util.List;
@Entity
public class OrderRequest {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(cascade = { CascadeType.REMOVE, CascadeType.PERSIST })
private ShipmentInfo shipmentInfo;
@OneToMany(orphanRemoval = true, cascade = CascadeType.PERSIST, mappedBy = "orderRequest")
private List<LineItem> lineItems;
public OrderRequest(ShipmentInfo shipmentInfo) {
this.shipmentInfo = shipmentInfo;
}
public OrderRequest(List<LineItem> lineItems) {
this.lineItems = lineItems;
}
public void removeLineItem(LineItem lineItem) {
lineItems.remove(lineItem);
}
public void setLineItems(List<LineItem> lineItems) {
this.lineItems = lineItems;
}
protected OrderRequest() {
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.jpa.removal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class ShipmentInfo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
public ShipmentInfo(String name) {
this.name = name;
}
protected ShipmentInfo() {
}
}

View File

@ -1,25 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<persistence-unit name="jpa-h2-equality">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.equality.EqualByJavaDefault</class>
<class>com.baeldung.jpa.equality.EqualById</class>
<class>com.baeldung.jpa.equality.EqualByBusinessKey</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test" />
<property name="javax.persistence.jdbc.user" value="sa" />
<property name="javax.persistence.jdbc.password" value="" />
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="show_sql" value="false" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false" />
</properties>
</persistence-unit>
version="2.2">
<persistence-unit name="jpa-h2-equality">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.equality.EqualByJavaDefault</class>
<class>com.baeldung.jpa.equality.EqualById</class>
<class>com.baeldung.jpa.equality.EqualByBusinessKey</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="show_sql" value="false"/>
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
</properties>
</persistence-unit>
<persistence-unit name="jpa-h2-removal">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.removal.ShipmentInfo</class>
<class>com.baeldung.jpa.removal.LineItem</class>
<class>com.baeldung.jpa.removal.OrderRequest</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="show_sql" value="false"/>
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,79 @@
package com.baeldung.ignorable.fields;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.io.*;
import java.util.List;
import java.util.Random;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
public class TransientFieldUnitTest {
private final UserDao userDao = new UserDao();
private final int randInt = new Random().nextInt();
private final User user = new User("user" + randInt + "@bar.com", "hunter2", "MacOSX");
@Test
public void givenFieldWithTransientAnnotation_whenSavingViaJPA_thenFieldIgnored() {
userDao.saveUser(user);
List<User> allUsers = userDao.getUsers();
User savedUser = allUsers.get(allUsers.indexOf(user));
assertNull(savedUser.getCurrentDevice());
}
@Test
public void givenFieldWithTransientAnnotation_whenSerializingObject_thenFieldSerialized() throws IOException, ClassNotFoundException {
FileOutputStream fout = new FileOutputStream("test.obj");
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(user);
out.flush();
out.close();
FileInputStream fin = new FileInputStream("test.obj");
ObjectInputStream in = new ObjectInputStream(fin);
User savedUser = (User) in.readObject();
in.close();
assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice());
}
@Test
public void givenFieldWithTransientAnnotation_whenSerializingToJSON_thenFieldSerialized() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(user);
User savedUser = objectMapper.readValue(json, User.class);
assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice());
}
@Test
public void givenJacksonHibernate5Module_whenSerializingTransientAnnotation_thenFieldIgnored() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Hibernate5Module());
String json = objectMapper.writeValueAsString(user);
User savedUser = objectMapper.readValue(json, User.class);
assertNull(savedUser.getCurrentDevice());
}
@Test
public void givenPropagateTransientFieldFlag_whenSerializingTransientAnnotation_thenFieldSerialized() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
String json = objectMapper.writeValueAsString(user);
User savedUser = objectMapper.readValue(json, User.class);
assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice());
}
}

View File

@ -0,0 +1,73 @@
package com.baeldung.jpa.removal;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.List;
public class CascadeTypeRemoveIntegrationTest {
private static EntityManagerFactory factory;
private static EntityManager entityManager;
@BeforeClass
public static void setup() {
factory = Persistence.createEntityManagerFactory("jpa-h2-removal");
entityManager = factory.createEntityManager();
}
@Test
public void whenOrderRequestIsDeleted_thenDeleteShipmentInfo() {
createOrderRequestWithShipmentInfo();
OrderRequest orderRequest = entityManager.find(OrderRequest.class, 1L);
entityManager.getTransaction().begin();
entityManager.remove(orderRequest);
entityManager.getTransaction().commit();
Assert.assertEquals(0, findAllOrderRequest().size());
Assert.assertEquals(0, findAllShipmentInfo().size());
}
private void createOrderRequestWithShipmentInfo() {
ShipmentInfo shipmentInfo = new ShipmentInfo("name");
OrderRequest orderRequest = new OrderRequest(shipmentInfo);
entityManager.getTransaction().begin();
entityManager.persist(orderRequest);
entityManager.getTransaction().commit();
Assert.assertEquals(1, findAllOrderRequest().size());
Assert.assertEquals(1, findAllShipmentInfo().size());
}
private List<OrderRequest> findAllOrderRequest() {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<OrderRequest> cq = cb.createQuery(OrderRequest.class);
Root<OrderRequest> root = cq.from(OrderRequest.class);
CriteriaQuery<OrderRequest> findAll = cq.select(root);
TypedQuery<OrderRequest> findAllQuery = entityManager.createQuery(findAll);
return findAllQuery.getResultList();
}
private List<ShipmentInfo> findAllShipmentInfo() {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<ShipmentInfo> cq = cb.createQuery(ShipmentInfo.class);
Root<ShipmentInfo> root = cq.from(ShipmentInfo.class);
CriteriaQuery<ShipmentInfo> findAll = cq.select(root);
TypedQuery<ShipmentInfo> findAllQuery = entityManager.createQuery(findAll);
return findAllQuery.getResultList();
}
}

View File

@ -0,0 +1,92 @@
package com.baeldung.jpa.removal;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
public class OrphanRemovalIntegrationTest {
private static EntityManagerFactory factory;
private static EntityManager entityManager;
@Before
public void setup() {
factory = Persistence.createEntityManagerFactory("jpa-h2-removal");
entityManager = factory.createEntityManager();
}
@Test
public void whenLineItemIsRemovedFromOrderRequest_thenDeleteOrphanedLineItem() {
createOrderRequestWithLineItems();
OrderRequest orderRequest = entityManager.find(OrderRequest.class, 1L);
LineItem lineItem = entityManager.find(LineItem.class, 2L);
orderRequest.removeLineItem(lineItem);
entityManager.getTransaction().begin();
entityManager.merge(orderRequest);
entityManager.getTransaction().commit();
Assert.assertEquals(1, findAllOrderRequest().size());
Assert.assertEquals(2, findAllLineItem().size());
}
@Test(expected = PersistenceException.class)
public void whenLineItemsIsReassigned_thenThrowAnException() {
createOrderRequestWithLineItems();
OrderRequest orderRequest = entityManager.find(OrderRequest.class, 1L);
orderRequest.setLineItems(new ArrayList<>());
entityManager.getTransaction().begin();
entityManager.merge(orderRequest);
entityManager.getTransaction().commit();
}
private void createOrderRequestWithLineItems() {
List<LineItem> lineItems = new ArrayList<>();
lineItems.add(new LineItem("line item 1"));
lineItems.add(new LineItem("line item 2"));
lineItems.add(new LineItem("line item 3"));
OrderRequest orderRequest = new OrderRequest(lineItems);
entityManager.getTransaction().begin();
entityManager.persist(orderRequest);
entityManager.getTransaction().commit();
Assert.assertEquals(1, findAllOrderRequest().size());
Assert.assertEquals(3, findAllLineItem().size());
}
private List<OrderRequest> findAllOrderRequest() {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<OrderRequest> cq = cb.createQuery(OrderRequest.class);
Root<OrderRequest> root = cq.from(OrderRequest.class);
CriteriaQuery<OrderRequest> findAll = cq.select(root);
TypedQuery<OrderRequest> findAllQuery = entityManager.createQuery(findAll);
return findAllQuery.getResultList();
}
private List<LineItem> findAllLineItem() {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<LineItem> cq = cb.createQuery(LineItem.class);
Root<LineItem> root = cq.from(LineItem.class);
CriteriaQuery<LineItem> findAll = cq.select(root);
TypedQuery<LineItem> findAllQuery = entityManager.createQuery(findAll);
return findAllQuery.getResultList();
}
}

View File

@ -397,6 +397,7 @@
<module>ddd</module>
<!-- <module>ddd-modules</module>--> <!-- we haven't upgraded to Java 9 -->
<module>deeplearning4j</module>
<module>discord4j</module>
<module>disruptor</module>
<module>dozer</module>
<module>drools</module>
@ -909,6 +910,7 @@
<module>ddd</module>
<!-- <module>ddd-modules</module>--> <!-- we haven't upgraded to Java 9 -->
<module>deeplearning4j</module>
<module>discord4j</module>
<module>disruptor</module>
<module>dozer</module>
<module>drools</module>

View File

@ -1,97 +0,0 @@
package com.baeldung.reactive;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import java.time.Duration;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import com.baeldung.web.reactive.Task;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.DisposableServer;
import reactor.netty.http.server.HttpServer;
public class Spring5ReactiveServerClientIntegrationTest {
private static DisposableServer disposableServer;
@BeforeAll
public static void setUp() throws Exception {
HttpServer server = HttpServer.create()
.host("localhost")
.port(8080);
RouterFunction<?> route = RouterFunctions.route(POST("/task/process"), request -> ServerResponse.ok()
.body(request.bodyToFlux(Task.class)
.map(ll -> new Task("TaskName", 1)), Task.class))
.and(RouterFunctions.route(GET("/task"), request -> ServerResponse.ok()
.body(Mono.just("server is alive"), String.class)));
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
disposableServer = server.handle(adapter)
.bindNow();
}
@AfterAll
public static void shutDown() {
disposableServer.disposeNow();
}
// @Test
// public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception {
// WebClient client = WebClient.create("http://localhost:8080");
// Mono<String> result = client
// .get()
// .uri("/task")
// .exchange()
// .then(response -> response.bodyToMono(String.class));
//
// assertThat(result.block()).isInstanceOf(String.class);
// }
// @Test
// public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception {
// URI uri = URI.create("http://localhost:8080/task/process");
// ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
// ClientRequest request = ClientRequest
// .method(HttpMethod.POST, uri)
// .body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
// .build();
//
// Flux<Task> taskResponse = exchange
// .exchange(request)
// .flatMap(response -> response.bodyToFlux(Task.class));
//
// assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class);
// }
// @Test
// public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception {
// URI uri = URI.create("http://localhost:8080/task");
// ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
// ClientRequest request = ClientRequest
// .method(HttpMethod.GET, uri)
// .body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
// .build();
//
// Flux<String> taskResponse = exchange
// .exchange(request)
// .flatMap(response -> response.bodyToFlux(String.class));
//
// assertThat(taskResponse.blockFirst()).isInstanceOf(String.class);
// }
private static Flux<Task> getLatLngs() {
return Flux.range(0, 3)
.zipWith(Flux.interval(Duration.ofSeconds(1)))
.map(x -> new Task("taskname", 1))
.doOnNext(ll -> System.out.println("Produced: {}" + ll));
}
}