Merge branch 'master' of https://github.com/eugenp/tutorials
This commit is contained in:
commit
080122250b
@ -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)
|
- [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)
|
- [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)
|
- [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)
|
||||||
|
@ -4,3 +4,5 @@
|
|||||||
- [IllegalArgumentException or NullPointerException for a Null Parameter?](https://www.baeldung.com/java-illegalargumentexception-or-nullpointerexception)
|
- [IllegalArgumentException or NullPointerException for a Null Parameter?](https://www.baeldung.com/java-illegalargumentexception-or-nullpointerexception)
|
||||||
- [IllegalMonitorStateException in Java](https://www.baeldung.com/java-illegalmonitorstateexception)
|
- [IllegalMonitorStateException in Java](https://www.baeldung.com/java-illegalmonitorstateexception)
|
||||||
- [AbstractMethodError in Java](https://www.baeldung.com/java-abstractmethoderror)
|
- [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)
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
message.exception = I am an exception.
|
@ -0,0 +1 @@
|
|||||||
|
message.exception = Je suis une exception.
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +1,3 @@
|
|||||||
## Relevant articles:
|
## Relevant articles:
|
||||||
|
|
||||||
|
- [Functional Programming in Java](https://www.baeldung.com/java-functional-programming)
|
||||||
|
@ -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)
|
- [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)
|
- [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)
|
- [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)
|
- [[<-- Prev]](/core-java-modules/core-java-lang-2)
|
||||||
|
@ -12,3 +12,4 @@ This module contains articles about types in Java
|
|||||||
- [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values)
|
- [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)
|
- [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)
|
- [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)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [Version Comparison in Java](https://www.baeldung.com/java-comparing-versions)
|
- [Version Comparison in Java](https://www.baeldung.com/java-comparing-versions)
|
||||||
|
- [Java (String) or .toString()?](https://www.baeldung.com/java-string-casting-vs-tostring)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
@ -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.*
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
import kotlinx.coroutines.channels.produce
|
import kotlinx.coroutines.channels.produce
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.channels.ticker
|
import kotlinx.coroutines.channels.ticker
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.channles
|
package com.baeldung.channels
|
||||||
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
33
discord4j/.gitignore
vendored
Normal file
33
discord4j/.gitignore
vendored
Normal 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
63
discord4j/pom.xml
Normal 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>
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
1
discord4j/src/main/resources/application.yml
Normal file
1
discord4j/src/main/resources/application.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
token: 'our-token-here'
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
- [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)
|
- [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)
|
||||||
|
@ -5,3 +5,4 @@ This module contains articles about the Java Persistence API (JPA) in Java.
|
|||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [JPA Entity Equality](https://www.baeldung.com/jpa-entity-equality)
|
- [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)
|
||||||
|
@ -27,7 +27,21 @@
|
|||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>${h2.version}</version>
|
<version>${h2.version}</version>
|
||||||
</dependency>
|
</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 -->
|
<!--Compile time JPA API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.persistence</groupId>
|
<groupId>javax.persistence</groupId>
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
@ -11,15 +11,33 @@
|
|||||||
<class>com.baeldung.jpa.equality.EqualByBusinessKey</class>
|
<class>com.baeldung.jpa.equality.EqualByBusinessKey</class>
|
||||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
|
<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.url" value="jdbc:h2:mem:test"/>
|
||||||
<property name="javax.persistence.jdbc.user" value="sa" />
|
<property name="javax.persistence.jdbc.user" value="sa"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="" />
|
<property name="javax.persistence.jdbc.password" value=""/>
|
||||||
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
|
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
|
||||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
|
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
|
||||||
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
|
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||||
<property name="show_sql" value="false" />
|
<property name="show_sql" value="false"/>
|
||||||
<property name="hibernate.temp.use_jdbc_metadata_defaults" 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>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
2
pom.xml
2
pom.xml
@ -397,6 +397,7 @@
|
|||||||
<module>ddd</module>
|
<module>ddd</module>
|
||||||
<!-- <module>ddd-modules</module>--> <!-- we haven't upgraded to Java 9 -->
|
<!-- <module>ddd-modules</module>--> <!-- we haven't upgraded to Java 9 -->
|
||||||
<module>deeplearning4j</module>
|
<module>deeplearning4j</module>
|
||||||
|
<module>discord4j</module>
|
||||||
<module>disruptor</module>
|
<module>disruptor</module>
|
||||||
<module>dozer</module>
|
<module>dozer</module>
|
||||||
<module>drools</module>
|
<module>drools</module>
|
||||||
@ -909,6 +910,7 @@
|
|||||||
<module>ddd</module>
|
<module>ddd</module>
|
||||||
<!-- <module>ddd-modules</module>--> <!-- we haven't upgraded to Java 9 -->
|
<!-- <module>ddd-modules</module>--> <!-- we haven't upgraded to Java 9 -->
|
||||||
<module>deeplearning4j</module>
|
<module>deeplearning4j</module>
|
||||||
|
<module>discord4j</module>
|
||||||
<module>disruptor</module>
|
<module>disruptor</module>
|
||||||
<module>dozer</module>
|
<module>dozer</module>
|
||||||
<module>drools</module>
|
<module>drools</module>
|
||||||
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user