diff --git a/algorithms-genetic/pom.xml b/algorithms-genetic/pom.xml index 942acd69c6..4d15464138 100644 --- a/algorithms-genetic/pom.xml +++ b/algorithms-genetic/pom.xml @@ -44,18 +44,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 3.6.1 3.7.0 diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index d9ecbd78e8..00cb4eeda9 100644 --- a/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-miscellaneous-1/pom.xml @@ -49,18 +49,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - diff --git a/algorithms-miscellaneous-2/pom.xml b/algorithms-miscellaneous-2/pom.xml index 7144a7a391..89d5b3657a 100644 --- a/algorithms-miscellaneous-2/pom.xml +++ b/algorithms-miscellaneous-2/pom.xml @@ -54,18 +54,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - diff --git a/algorithms-miscellaneous-3/pom.xml b/algorithms-miscellaneous-3/pom.xml index 4b67a30abb..166a7be623 100644 --- a/algorithms-miscellaneous-3/pom.xml +++ b/algorithms-miscellaneous-3/pom.xml @@ -74,18 +74,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 3.9.0 4.3 diff --git a/algorithms-miscellaneous-4/pom.xml b/algorithms-miscellaneous-4/pom.xml index 50fef5ff71..31a6db5354 100644 --- a/algorithms-miscellaneous-4/pom.xml +++ b/algorithms-miscellaneous-4/pom.xml @@ -34,18 +34,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 3.9.0 27.0.1-jre diff --git a/algorithms-miscellaneous-5/pom.xml b/algorithms-miscellaneous-5/pom.xml index 615cf03467..71a5a3d410 100644 --- a/algorithms-miscellaneous-5/pom.xml +++ b/algorithms-miscellaneous-5/pom.xml @@ -49,18 +49,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 1.0.1 3.9.0 diff --git a/algorithms-sorting-2/pom.xml b/algorithms-sorting-2/pom.xml index 529474afda..5ef90b9825 100644 --- a/algorithms-sorting-2/pom.xml +++ b/algorithms-sorting-2/pom.xml @@ -44,18 +44,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 3.6.1 3.9.0 diff --git a/algorithms-sorting/pom.xml b/algorithms-sorting/pom.xml index 2de8eed04e..1d0b7718ac 100644 --- a/algorithms-sorting/pom.xml +++ b/algorithms-sorting/pom.xml @@ -45,18 +45,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 3.6.1 3.9.0 diff --git a/apache-cxf/pom.xml b/apache-cxf/pom.xml index 3d64000c2e..0975996c06 100644 --- a/apache-cxf/pom.xml +++ b/apache-cxf/pom.xml @@ -30,7 +30,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} diff --git a/aws-lambda/lambda/pom.xml b/aws-lambda/lambda/pom.xml index 1f446e04c0..463d106c77 100644 --- a/aws-lambda/lambda/pom.xml +++ b/aws-lambda/lambda/pom.xml @@ -4,9 +4,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - aws-lambda-examples + lambda 0.1.0-SNAPSHOT - aws-lambda-examples + lambda jar diff --git a/aws-lambda/shipping-tracker/ShippingFunction/pom.xml b/aws-lambda/shipping-tracker/ShippingFunction/pom.xml index ac39c9ea54..2c8224e6d5 100644 --- a/aws-lambda/shipping-tracker/ShippingFunction/pom.xml +++ b/aws-lambda/shipping-tracker/ShippingFunction/pom.xml @@ -5,7 +5,7 @@ ShippingFunction 1.0 jar - Shipping Tracker Lambda Function + ShippingFunction 1.8 1.8 diff --git a/axon/pom.xml b/axon/pom.xml index f6c43c7cbd..f2cdc34fd1 100644 --- a/axon/pom.xml +++ b/axon/pom.xml @@ -53,7 +53,7 @@ - 4.1.2 + 4.4.7 \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java b/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java deleted file mode 100644 index 4ef02e6b54..0000000000 --- a/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.baeldung.axon.commandmodel; - -import static org.axonframework.modelling.command.AggregateLifecycle.apply; - -import org.axonframework.commandhandling.CommandHandler; -import org.axonframework.eventsourcing.EventSourcingHandler; -import org.axonframework.modelling.command.AggregateIdentifier; -import org.axonframework.spring.stereotype.Aggregate; - -import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; -import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; -import com.baeldung.axon.coreapi.commands.ShipOrderCommand; -import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; -import com.baeldung.axon.coreapi.events.OrderPlacedEvent; -import com.baeldung.axon.coreapi.events.OrderShippedEvent; -import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException; - -@Aggregate -public class OrderAggregate { - - @AggregateIdentifier - private String orderId; - private boolean orderConfirmed; - - @CommandHandler - public OrderAggregate(PlaceOrderCommand command) { - apply(new OrderPlacedEvent(command.getOrderId(), command.getProduct())); - } - - @CommandHandler - public void handle(ConfirmOrderCommand command) { - apply(new OrderConfirmedEvent(orderId)); - } - - @CommandHandler - public void handle(ShipOrderCommand command) { - if (!orderConfirmed) { - throw new UnconfirmedOrderException(); - } - - apply(new OrderShippedEvent(orderId)); - } - - @EventSourcingHandler - public void on(OrderPlacedEvent event) { - this.orderId = event.getOrderId(); - this.orderConfirmed = false; - } - - @EventSourcingHandler - public void on(OrderConfirmedEvent event) { - this.orderConfirmed = true; - } - - protected OrderAggregate() { - // Required by Axon to build a default Aggregate prior to Event Sourcing - } - -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java new file mode 100644 index 0000000000..97342bdb3a --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderAggregate.java @@ -0,0 +1,98 @@ +package com.baeldung.axon.commandmodel.order; + +import com.baeldung.axon.coreapi.commands.AddProductCommand; +import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; +import com.baeldung.axon.coreapi.commands.CreateOrderCommand; +import com.baeldung.axon.coreapi.commands.ShipOrderCommand; +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.OrderCreatedEvent; +import com.baeldung.axon.coreapi.events.OrderShippedEvent; +import com.baeldung.axon.coreapi.events.ProductAddedEvent; +import com.baeldung.axon.coreapi.events.ProductRemovedEvent; +import com.baeldung.axon.coreapi.exceptions.DuplicateOrderLineException; +import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException; +import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException; +import org.axonframework.commandhandling.CommandHandler; +import org.axonframework.eventsourcing.EventSourcingHandler; +import org.axonframework.modelling.command.AggregateIdentifier; +import org.axonframework.modelling.command.AggregateMember; +import org.axonframework.spring.stereotype.Aggregate; + +import java.util.HashMap; +import java.util.Map; + +import static org.axonframework.modelling.command.AggregateLifecycle.apply; + +@Aggregate +public class OrderAggregate { + + @AggregateIdentifier + private String orderId; + private boolean orderConfirmed; + + @AggregateMember + private Map orderLines; + + @CommandHandler + public OrderAggregate(CreateOrderCommand command) { + apply(new OrderCreatedEvent(command.getOrderId())); + } + + @CommandHandler + public void handle(AddProductCommand command) { + if (orderConfirmed) { + throw new OrderAlreadyConfirmedException(orderId); + } + + String productId = command.getProductId(); + if (orderLines.containsKey(productId)) { + throw new DuplicateOrderLineException(productId); + } + apply(new ProductAddedEvent(orderId, productId)); + } + + @CommandHandler + public void handle(ConfirmOrderCommand command) { + if (orderConfirmed) { + return; + } + + apply(new OrderConfirmedEvent(orderId)); + } + + @CommandHandler + public void handle(ShipOrderCommand command) { + if (!orderConfirmed) { + throw new UnconfirmedOrderException(); + } + + apply(new OrderShippedEvent(orderId)); + } + + @EventSourcingHandler + public void on(OrderCreatedEvent event) { + this.orderId = event.getOrderId(); + this.orderConfirmed = false; + this.orderLines = new HashMap<>(); + } + + @EventSourcingHandler + public void on(OrderConfirmedEvent event) { + this.orderConfirmed = true; + } + + @EventSourcingHandler + public void on(ProductAddedEvent event) { + String productId = event.getProductId(); + this.orderLines.put(productId, new OrderLine(productId)); + } + + @EventSourcingHandler + public void on(ProductRemovedEvent event) { + this.orderLines.remove(event.getProductId()); + } + + protected OrderAggregate() { + // Required by Axon to build a default Aggregate prior to Event Sourcing + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java new file mode 100644 index 0000000000..e471ecbfe0 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/commandmodel/order/OrderLine.java @@ -0,0 +1,83 @@ +package com.baeldung.axon.commandmodel.order; + +import com.baeldung.axon.coreapi.commands.DecrementProductCountCommand; +import com.baeldung.axon.coreapi.commands.IncrementProductCountCommand; +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent; +import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent; +import com.baeldung.axon.coreapi.events.ProductRemovedEvent; +import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException; +import org.axonframework.commandhandling.CommandHandler; +import org.axonframework.eventsourcing.EventSourcingHandler; +import org.axonframework.modelling.command.EntityId; + +import java.util.Objects; + +import static org.axonframework.modelling.command.AggregateLifecycle.apply; + +public class OrderLine { + + @EntityId + private final String productId; + private Integer count; + private boolean orderConfirmed; + + public OrderLine(String productId) { + this.productId = productId; + this.count = 1; + } + + @CommandHandler + public void handle(IncrementProductCountCommand command) { + if (orderConfirmed) { + throw new OrderAlreadyConfirmedException(command.getOrderId()); + } + + apply(new ProductCountIncrementedEvent(command.getOrderId(), productId)); + } + + @CommandHandler + public void handle(DecrementProductCountCommand command) { + if (orderConfirmed) { + throw new OrderAlreadyConfirmedException(command.getOrderId()); + } + + if (count <= 1) { + apply(new ProductRemovedEvent(command.getOrderId(), productId)); + } else { + apply(new ProductCountDecrementedEvent(command.getOrderId(), productId)); + } + } + + @EventSourcingHandler + public void on(ProductCountIncrementedEvent event) { + this.count++; + } + + @EventSourcingHandler + public void on(ProductCountDecrementedEvent event) { + this.count--; + } + + @EventSourcingHandler + public void on(OrderConfirmedEvent event) { + this.orderConfirmed = true; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrderLine orderLine = (OrderLine) o; + return Objects.equals(productId, orderLine.productId) && Objects.equals(count, orderLine.count); + } + + @Override + public int hashCode() { + return Objects.hash(productId, count); + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java new file mode 100644 index 0000000000..28736aaadc --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/AddProductCommand.java @@ -0,0 +1,50 @@ +package com.baeldung.axon.coreapi.commands; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +import java.util.Objects; + +public class AddProductCommand { + + @TargetAggregateIdentifier + private final String orderId; + private final String productId; + + public AddProductCommand(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AddProductCommand that = (AddProductCommand) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "AddProductCommand{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java new file mode 100644 index 0000000000..ceb7fd6a08 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/CreateOrderCommand.java @@ -0,0 +1,43 @@ +package com.baeldung.axon.coreapi.commands; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +import java.util.Objects; + +public class CreateOrderCommand { + + @TargetAggregateIdentifier + private final String orderId; + + public CreateOrderCommand(String orderId) { + this.orderId = orderId; + } + + public String getOrderId() { + return orderId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CreateOrderCommand that = (CreateOrderCommand) o; + return Objects.equals(orderId, that.orderId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId); + } + + @Override + public String toString() { + return "CreateOrderCommand{" + + "orderId='" + orderId + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java new file mode 100644 index 0000000000..f6f4db00fc --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/DecrementProductCountCommand.java @@ -0,0 +1,50 @@ +package com.baeldung.axon.coreapi.commands; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +import java.util.Objects; + +public class DecrementProductCountCommand { + + @TargetAggregateIdentifier + private final String orderId; + private final String productId; + + public DecrementProductCountCommand(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DecrementProductCountCommand that = (DecrementProductCountCommand) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "DecrementProductCountCommand{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java new file mode 100644 index 0000000000..548faabe37 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/IncrementProductCountCommand.java @@ -0,0 +1,50 @@ +package com.baeldung.axon.coreapi.commands; + +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +import java.util.Objects; + +public class IncrementProductCountCommand { + + @TargetAggregateIdentifier + private final String orderId; + private final String productId; + + public IncrementProductCountCommand(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IncrementProductCountCommand that = (IncrementProductCountCommand) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "IncrementProductCountCommand{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java deleted file mode 100644 index c70d503050..0000000000 --- a/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.axon.coreapi.commands; - -import java.util.Objects; - -import org.axonframework.modelling.command.TargetAggregateIdentifier; - -public class PlaceOrderCommand { - - @TargetAggregateIdentifier - private final String orderId; - private final String product; - - public PlaceOrderCommand(String orderId, String product) { - this.orderId = orderId; - this.product = product; - } - - public String getOrderId() { - return orderId; - } - - public String getProduct() { - return product; - } - - @Override - public int hashCode() { - return Objects.hash(orderId, product); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final PlaceOrderCommand other = (PlaceOrderCommand) obj; - return Objects.equals(this.orderId, other.orderId) - && Objects.equals(this.product, other.product); - } - - @Override - public String toString() { - return "PlaceOrderCommand{" + - "orderId='" + orderId + '\'' + - ", product='" + product + '\'' + - '}'; - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java new file mode 100644 index 0000000000..5d2d8b7f55 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderCreatedEvent.java @@ -0,0 +1,40 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class OrderCreatedEvent { + + private final String orderId; + + public OrderCreatedEvent(String orderId) { + this.orderId = orderId; + } + + public String getOrderId() { + return orderId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrderCreatedEvent that = (OrderCreatedEvent) o; + return Objects.equals(orderId, that.orderId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId); + } + + @Override + public String toString() { + return "OrderCreatedEvent{" + + "orderId='" + orderId + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java deleted file mode 100644 index 06de4c5f9f..0000000000 --- a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.axon.coreapi.events; - -import java.util.Objects; - -public class OrderPlacedEvent { - - private final String orderId; - private final String product; - - public OrderPlacedEvent(String orderId, String product) { - this.orderId = orderId; - this.product = product; - } - - public String getOrderId() { - return orderId; - } - - public String getProduct() { - return product; - } - - @Override - public int hashCode() { - return Objects.hash(orderId, product); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final OrderPlacedEvent other = (OrderPlacedEvent) obj; - return Objects.equals(this.orderId, other.orderId) - && Objects.equals(this.product, other.product); - } - - @Override - public String toString() { - return "OrderPlacedEvent{" + - "orderId='" + orderId + '\'' + - ", product='" + product + '\'' + - '}'; - } -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java new file mode 100644 index 0000000000..091ef2a570 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductAddedEvent.java @@ -0,0 +1,47 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class ProductAddedEvent { + + private final String orderId; + private final String productId; + + public ProductAddedEvent(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProductAddedEvent that = (ProductAddedEvent) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "ProductAddedEvent{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java new file mode 100644 index 0000000000..4017916791 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountDecrementedEvent.java @@ -0,0 +1,47 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class ProductCountDecrementedEvent { + + private final String orderId; + private final String productId; + + public ProductCountDecrementedEvent(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProductCountDecrementedEvent that = (ProductCountDecrementedEvent) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "ProductCountDecrementedEvent{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java new file mode 100644 index 0000000000..2910a9ea6f --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductCountIncrementedEvent.java @@ -0,0 +1,47 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class ProductCountIncrementedEvent { + + private final String orderId; + private final String productId; + + public ProductCountIncrementedEvent(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProductCountIncrementedEvent that = (ProductCountIncrementedEvent) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "ProductCountIncrementedEvent{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java new file mode 100644 index 0000000000..7f89ccd1cc --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/ProductRemovedEvent.java @@ -0,0 +1,47 @@ +package com.baeldung.axon.coreapi.events; + +import java.util.Objects; + +public class ProductRemovedEvent { + + private final String orderId; + private final String productId; + + public ProductRemovedEvent(String orderId, String productId) { + this.orderId = orderId; + this.productId = productId; + } + + public String getOrderId() { + return orderId; + } + + public String getProductId() { + return productId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProductRemovedEvent that = (ProductRemovedEvent) o; + return Objects.equals(orderId, that.orderId) && Objects.equals(productId, that.productId); + } + + @Override + public int hashCode() { + return Objects.hash(orderId, productId); + } + + @Override + public String toString() { + return "ProductRemovedEvent{" + + "orderId='" + orderId + '\'' + + ", productId='" + productId + '\'' + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/exceptions/DuplicateOrderLineException.java b/axon/src/main/java/com/baeldung/axon/coreapi/exceptions/DuplicateOrderLineException.java new file mode 100644 index 0000000000..c8a62a6cf0 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/exceptions/DuplicateOrderLineException.java @@ -0,0 +1,8 @@ +package com.baeldung.axon.coreapi.exceptions; + +public class DuplicateOrderLineException extends IllegalStateException { + + public DuplicateOrderLineException(String productId) { + super("Cannot duplicate order line for product identifier [" + productId + "]"); + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/exceptions/OrderAlreadyConfirmedException.java b/axon/src/main/java/com/baeldung/axon/coreapi/exceptions/OrderAlreadyConfirmedException.java new file mode 100644 index 0000000000..5a4d1cdaec --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/exceptions/OrderAlreadyConfirmedException.java @@ -0,0 +1,8 @@ +package com.baeldung.axon.coreapi.exceptions; + +public class OrderAlreadyConfirmedException extends IllegalStateException { + + public OrderAlreadyConfirmedException(String orderId) { + super("Cannot perform operation because order [" + orderId + "] is already confirmed."); + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java new file mode 100644 index 0000000000..1810a053d3 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/Order.java @@ -0,0 +1,83 @@ +package com.baeldung.axon.coreapi.queries; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class Order { + + private final String orderId; + private final Map products; + private OrderStatus orderStatus; + + public Order(String orderId) { + this.orderId = orderId; + this.products = new HashMap<>(); + orderStatus = OrderStatus.CREATED; + } + + public String getOrderId() { + return orderId; + } + + public Map getProducts() { + return products; + } + + public OrderStatus getOrderStatus() { + return orderStatus; + } + + public void addProduct(String productId) { + products.putIfAbsent(productId, 1); + } + + public void incrementProductInstance(String productId) { + products.computeIfPresent(productId, (id, count) -> ++count); + } + + public void decrementProductInstance(String productId) { + products.computeIfPresent(productId, (id, count) -> --count); + } + + + public void removeProduct(String productId) { + products.remove(productId); + } + + public void setOrderConfirmed() { + this.orderStatus = OrderStatus.CONFIRMED; + } + + public void setOrderShipped() { + this.orderStatus = OrderStatus.SHIPPED; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order that = (Order) o; + return Objects.equals(orderId, that.orderId) + && Objects.equals(products, that.products) + && orderStatus == that.orderStatus; + } + + @Override + public int hashCode() { + return Objects.hash(orderId, products, orderStatus); + } + + @Override + public String toString() { + return "Order{" + + "orderId='" + orderId + '\'' + + ", products=" + products + + ", orderStatus=" + orderStatus + + '}'; + } +} diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java index d215c5fc32..fc5da5d77e 100644 --- a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java +++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java @@ -2,6 +2,5 @@ package com.baeldung.axon.coreapi.queries; public enum OrderStatus { - PLACED, CONFIRMED, SHIPPED - + CREATED, CONFIRMED, SHIPPED } diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java deleted file mode 100644 index d847bb2a98..0000000000 --- a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.axon.coreapi.queries; - -import java.util.Objects; - -public class OrderedProduct { - - private final String orderId; - private final String product; - private OrderStatus orderStatus; - - public OrderedProduct(String orderId, String product) { - this.orderId = orderId; - this.product = product; - orderStatus = OrderStatus.PLACED; - } - - public String getOrderId() { - return orderId; - } - - public String getProduct() { - return product; - } - - public OrderStatus getOrderStatus() { - return orderStatus; - } - - public void setOrderConfirmed() { - this.orderStatus = OrderStatus.CONFIRMED; - } - - public void setOrderShipped() { - this.orderStatus = OrderStatus.SHIPPED; - } - - @Override - public int hashCode() { - return Objects.hash(orderId, product, orderStatus); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final OrderedProduct other = (OrderedProduct) obj; - return Objects.equals(this.orderId, other.orderId) - && Objects.equals(this.product, other.product) - && Objects.equals(this.orderStatus, other.orderStatus); - } - - @Override - public String toString() { - return "OrderedProduct{" + - "orderId='" + orderId + '\'' + - ", product='" + product + '\'' + - ", orderStatus=" + orderStatus + - '}'; - } -} diff --git a/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java index a9f34cc691..11e03bf6a5 100644 --- a/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java +++ b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java @@ -1,20 +1,24 @@ package com.baeldung.axon.gui; -import java.util.List; -import java.util.UUID; - +import com.baeldung.axon.coreapi.commands.AddProductCommand; +import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; +import com.baeldung.axon.coreapi.commands.CreateOrderCommand; +import com.baeldung.axon.coreapi.commands.DecrementProductCountCommand; +import com.baeldung.axon.coreapi.commands.IncrementProductCountCommand; +import com.baeldung.axon.coreapi.commands.ShipOrderCommand; +import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery; +import com.baeldung.axon.coreapi.queries.Order; import org.axonframework.commandhandling.gateway.CommandGateway; import org.axonframework.messaging.responsetypes.ResponseTypes; import org.axonframework.queryhandling.QueryGateway; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; -import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; -import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; -import com.baeldung.axon.coreapi.commands.ShipOrderCommand; -import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery; -import com.baeldung.axon.coreapi.queries.OrderedProduct; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; @RestController public class OrderRestEndpoint { @@ -28,25 +32,63 @@ public class OrderRestEndpoint { } @PostMapping("/ship-order") - public void shipOrder() { + public CompletableFuture shipOrder() { String orderId = UUID.randomUUID().toString(); - commandGateway.send(new PlaceOrderCommand(orderId, "Deluxe Chair")); - commandGateway.send(new ConfirmOrderCommand(orderId)); - commandGateway.send(new ShipOrderCommand(orderId)); + return commandGateway.send(new CreateOrderCommand(orderId)) + .thenCompose(result -> commandGateway.send(new AddProductCommand(orderId, "Deluxe Chair"))) + .thenCompose(result -> commandGateway.send(new ConfirmOrderCommand(orderId))) + .thenCompose(result -> commandGateway.send(new ShipOrderCommand(orderId))); } @PostMapping("/ship-unconfirmed-order") - public void shipUnconfirmedOrder() { + public CompletableFuture shipUnconfirmedOrder() { String orderId = UUID.randomUUID().toString(); - commandGateway.send(new PlaceOrderCommand(orderId, "Deluxe Chair")); - // This throws an exception, as an Order cannot be shipped if it has not been confirmed yet. - commandGateway.send(new ShipOrderCommand(orderId)); + return commandGateway.send(new CreateOrderCommand(orderId)) + .thenCompose(result -> commandGateway.send(new AddProductCommand(orderId, "Deluxe Chair"))) + // This throws an exception, as an Order cannot be shipped if it has not been confirmed yet. + .thenCompose(result -> commandGateway.send(new ShipOrderCommand(orderId))); + } + + @PostMapping("/order") + public CompletableFuture createOrder() { + return createOrder(UUID.randomUUID().toString()); + } + + @PostMapping("/order/{order-id}") + public CompletableFuture createOrder(@PathVariable("order-id") String orderId) { + return commandGateway.send(new CreateOrderCommand(orderId)); + } + + @PostMapping("/order/{order-id}/product/{product-id}") + public CompletableFuture addProduct(@PathVariable("order-id") String orderId, + @PathVariable("product-id") String productId) { + return commandGateway.send(new AddProductCommand(orderId, productId)); + } + + @PostMapping("/order/{order-id}/product/{product-id}/increment") + public CompletableFuture incrementProduct(@PathVariable("order-id") String orderId, + @PathVariable("product-id") String productId) { + return commandGateway.send(new IncrementProductCountCommand(orderId, productId)); + } + + @PostMapping("/order/{order-id}/product/{product-id}/decrement") + public CompletableFuture decrementProduct(@PathVariable("order-id") String orderId, + @PathVariable("product-id") String productId) { + return commandGateway.send(new DecrementProductCountCommand(orderId, productId)); + } + + @PostMapping("/order/{order-id}/confirm") + public CompletableFuture confirmOrder(@PathVariable("order-id") String orderId) { + return commandGateway.send(new ConfirmOrderCommand(orderId)); + } + + @PostMapping("/order/{order-id}/ship") + public CompletableFuture shipOrder(@PathVariable("order-id") String orderId) { + return commandGateway.send(new ShipOrderCommand(orderId)); } @GetMapping("/all-orders") - public List findAllOrderedProducts() { - return queryGateway.query(new FindAllOrderedProductsQuery(), ResponseTypes.multipleInstancesOf(OrderedProduct.class)) - .join(); + public CompletableFuture> findAllOrders() { + return queryGateway.query(new FindAllOrderedProductsQuery(), ResponseTypes.multipleInstancesOf(Order.class)); } - } diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java deleted file mode 100644 index a37f0111ed..0000000000 --- a/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.axon.querymodel; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.axonframework.config.ProcessingGroup; -import org.axonframework.eventhandling.EventHandler; -import org.axonframework.queryhandling.QueryHandler; -import org.springframework.stereotype.Service; - -import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; -import com.baeldung.axon.coreapi.events.OrderPlacedEvent; -import com.baeldung.axon.coreapi.events.OrderShippedEvent; -import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery; -import com.baeldung.axon.coreapi.queries.OrderedProduct; - -@Service -@ProcessingGroup("ordered-products") -public class OrderedProductsEventHandler { - - private final Map orderedProducts = new HashMap<>(); - - @EventHandler - public void on(OrderPlacedEvent event) { - String orderId = event.getOrderId(); - orderedProducts.put(orderId, new OrderedProduct(orderId, event.getProduct())); - } - - @EventHandler - public void on(OrderConfirmedEvent event) { - orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> { - orderedProduct.setOrderConfirmed(); - return orderedProduct; - }); - } - - @EventHandler - public void on(OrderShippedEvent event) { - orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> { - orderedProduct.setOrderShipped(); - return orderedProduct; - }); - } - - @QueryHandler - public List handle(FindAllOrderedProductsQuery query) { - return new ArrayList<>(orderedProducts.values()); - } - -} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java new file mode 100644 index 0000000000..25666b0bf3 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/querymodel/OrdersEventHandler.java @@ -0,0 +1,86 @@ +package com.baeldung.axon.querymodel; + +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.OrderCreatedEvent; +import com.baeldung.axon.coreapi.events.OrderShippedEvent; +import com.baeldung.axon.coreapi.events.ProductAddedEvent; +import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent; +import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent; +import com.baeldung.axon.coreapi.events.ProductRemovedEvent; +import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery; +import com.baeldung.axon.coreapi.queries.Order; +import org.axonframework.config.ProcessingGroup; +import org.axonframework.eventhandling.EventHandler; +import org.axonframework.queryhandling.QueryHandler; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@ProcessingGroup("orders") +public class OrdersEventHandler { + + private final Map orders = new HashMap<>(); + + @EventHandler + public void on(OrderCreatedEvent event) { + String orderId = event.getOrderId(); + orders.put(orderId, new Order(orderId)); + } + + @EventHandler + public void on(ProductAddedEvent event) { + orders.computeIfPresent(event.getOrderId(), (orderId, order) -> { + order.addProduct(event.getProductId()); + return order; + }); + } + + @EventHandler + public void on(ProductCountIncrementedEvent event) { + orders.computeIfPresent(event.getOrderId(), (orderId, order) -> { + order.incrementProductInstance(event.getProductId()); + return order; + }); + } + + @EventHandler + public void on(ProductCountDecrementedEvent event) { + orders.computeIfPresent(event.getOrderId(), (orderId, order) -> { + order.decrementProductInstance(event.getProductId()); + return order; + }); + } + + @EventHandler + public void on(ProductRemovedEvent event) { + orders.computeIfPresent(event.getOrderId(), (orderId, order) -> { + order.removeProduct(event.getProductId()); + return order; + }); + } + + @EventHandler + public void on(OrderConfirmedEvent event) { + orders.computeIfPresent(event.getOrderId(), (orderId, order) -> { + order.setOrderConfirmed(); + return order; + }); + } + + @EventHandler + public void on(OrderShippedEvent event) { + orders.computeIfPresent(event.getOrderId(), (orderId, order) -> { + order.setOrderShipped(); + return order; + }); + } + + @QueryHandler + public List handle(FindAllOrderedProductsQuery query) { + return new ArrayList<>(orders.values()); + } +} \ No newline at end of file diff --git a/axon/src/main/resources/order-api.http b/axon/src/main/resources/order-api.http index a3c69c72bc..6c06c48989 100644 --- a/axon/src/main/resources/order-api.http +++ b/axon/src/main/resources/order-api.http @@ -1,11 +1,37 @@ +### Create Order, Add Product, Confirm and Ship Order + POST http://localhost:8080/ship-order -### +### Create Order, Add Product and Ship Order POST http://localhost:8080/ship-unconfirmed-order -### +### Retrieve all existing Orders GET http://localhost:8080/all-orders +### Create Order with id 666a1661-474d-4046-8b12-8b5896312768 + +POST http://localhost:8080/order/666a1661-474d-4046-8b12-8b5896312768 + +### Add Product a6aa01eb-4e38-4dfb-b53b-b5b82961fbf3 to Order 666a1661-474d-4046-8b12-8b5896312768 + +POST http://localhost:8080/order/666a1661-474d-4046-8b12-8b5896312768/product/a6aa01eb-4e38-4dfb-b53b-b5b82961fbf3 + +### Increment Product a6aa01eb-4e38-4dfb-b53b-b5b82961fbf3 to Order 666a1661-474d-4046-8b12-8b5896312768 + +POST http://localhost:8080/order/666a1661-474d-4046-8b12-8b5896312768/product/a6aa01eb-4e38-4dfb-b53b-b5b82961fbf3/increment + +### Decrement Product a6aa01eb-4e38-4dfb-b53b-b5b82961fbf3 to Order 666a1661-474d-4046-8b12-8b5896312768 + +POST http://localhost:8080/order/666a1661-474d-4046-8b12-8b5896312768/product/a6aa01eb-4e38-4dfb-b53b-b5b82961fbf3/decrement + +### Confirm Order 666a1661-474d-4046-8b12-8b5896312768 + +POST http://localhost:8080/order/666a1661-474d-4046-8b12-8b5896312768/confirm + +### Ship Order 666a1661-474d-4046-8b12-8b5896312768 + +POST http://localhost:8080/order/666a1661-474d-4046-8b12-8b5896312768/ship + ### diff --git a/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java index aaefe49fb1..c1d6bdccc2 100644 --- a/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java +++ b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java @@ -1,62 +1,139 @@ package com.baeldung.axon.commandmodel; -import java.util.UUID; - +import com.baeldung.axon.commandmodel.order.OrderAggregate; +import com.baeldung.axon.coreapi.commands.AddProductCommand; +import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; +import com.baeldung.axon.coreapi.commands.CreateOrderCommand; +import com.baeldung.axon.coreapi.commands.DecrementProductCountCommand; +import com.baeldung.axon.coreapi.commands.IncrementProductCountCommand; +import com.baeldung.axon.coreapi.commands.ShipOrderCommand; +import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; +import com.baeldung.axon.coreapi.events.OrderCreatedEvent; +import com.baeldung.axon.coreapi.events.OrderShippedEvent; +import com.baeldung.axon.coreapi.events.ProductAddedEvent; +import com.baeldung.axon.coreapi.events.ProductCountDecrementedEvent; +import com.baeldung.axon.coreapi.events.ProductCountIncrementedEvent; +import com.baeldung.axon.coreapi.events.ProductRemovedEvent; +import com.baeldung.axon.coreapi.exceptions.DuplicateOrderLineException; +import com.baeldung.axon.coreapi.exceptions.OrderAlreadyConfirmedException; import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException; import org.axonframework.test.aggregate.AggregateTestFixture; import org.axonframework.test.aggregate.FixtureConfiguration; -import org.junit.*; +import org.axonframework.test.matchers.Matchers; +import org.junit.jupiter.api.*; -import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand; -import com.baeldung.axon.coreapi.commands.PlaceOrderCommand; -import com.baeldung.axon.coreapi.commands.ShipOrderCommand; -import com.baeldung.axon.coreapi.events.OrderConfirmedEvent; -import com.baeldung.axon.coreapi.events.OrderPlacedEvent; -import com.baeldung.axon.coreapi.events.OrderShippedEvent; +import java.util.UUID; -public class OrderAggregateUnitTest { +class OrderAggregateUnitTest { + + private static final String ORDER_ID = UUID.randomUUID().toString(); + private static final String PRODUCT_ID = UUID.randomUUID().toString(); private FixtureConfiguration fixture; - @Before - public void setUp() { + @BeforeEach + void setUp() { fixture = new AggregateTestFixture<>(OrderAggregate.class); } @Test - public void giveNoPriorActivity_whenPlaceOrderCommand_thenShouldPublishOrderPlacedEvent() { - String orderId = UUID.randomUUID().toString(); - String product = "Deluxe Chair"; + void giveNoPriorActivity_whenCreateOrderCommand_thenShouldPublishOrderCreatedEvent() { fixture.givenNoPriorActivity() - .when(new PlaceOrderCommand(orderId, product)) - .expectEvents(new OrderPlacedEvent(orderId, product)); + .when(new CreateOrderCommand(ORDER_ID)) + .expectEvents(new OrderCreatedEvent(ORDER_ID)); } @Test - public void givenOrderPlacedEvent_whenConfirmOrderCommand_thenShouldPublishOrderConfirmedEvent() { - String orderId = UUID.randomUUID().toString(); - String product = "Deluxe Chair"; - fixture.given(new OrderPlacedEvent(orderId, product)) - .when(new ConfirmOrderCommand(orderId)) - .expectEvents(new OrderConfirmedEvent(orderId)); + void givenOrderCreatedEvent_whenAddProductCommand_thenShouldPublishProductAddedEvent() { + fixture.given(new OrderCreatedEvent(ORDER_ID)) + .when(new AddProductCommand(ORDER_ID, PRODUCT_ID)) + .expectEvents(new ProductAddedEvent(ORDER_ID, PRODUCT_ID)); } @Test - public void givenOrderPlacedEvent_whenShipOrderCommand_thenShouldThrowUnconfirmedOrderException() { - String orderId = UUID.randomUUID().toString(); - String product = "Deluxe Chair"; - fixture.given(new OrderPlacedEvent(orderId, product)) - .when(new ShipOrderCommand(orderId)) + void givenOrderCreatedEventAndProductAddedEvent_whenAddProductCommandForSameProductId_thenShouldThrowDuplicateOrderLineException() { + fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID)) + .when(new AddProductCommand(ORDER_ID, PRODUCT_ID)) + .expectException(DuplicateOrderLineException.class) + .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(PRODUCT_ID))); + } + + @Test + void givenOrderCreatedEventAndProductAddedEvent_whenIncrementProductCountCommand_thenShouldPublishProductCountIncrementedEvent() { + fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID)) + .when(new IncrementProductCountCommand(ORDER_ID, PRODUCT_ID)) + .expectEvents(new ProductCountIncrementedEvent(ORDER_ID, PRODUCT_ID)); + } + + @Test + void givenOrderCreatedEventProductAddedEventAndProductCountIncrementedEvent_whenDecrementProductCountCommand_thenShouldPublishProductCountDecrementedEvent() { + fixture.given(new OrderCreatedEvent(ORDER_ID), + new ProductAddedEvent(ORDER_ID, PRODUCT_ID), + new ProductCountIncrementedEvent(ORDER_ID, PRODUCT_ID)) + .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID)) + .expectEvents(new ProductCountDecrementedEvent(ORDER_ID, PRODUCT_ID)); + } + + @Test + void givenOrderCreatedEventAndProductAddedEvent_whenDecrementProductCountCommand_thenShouldPublishProductRemovedEvent() { + fixture.given(new OrderCreatedEvent(ORDER_ID), new ProductAddedEvent(ORDER_ID, PRODUCT_ID)) + .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID)) + .expectEvents(new ProductRemovedEvent(ORDER_ID, PRODUCT_ID)); + } + + @Test + void givenOrderCreatedEvent_whenConfirmOrderCommand_thenShouldPublishOrderConfirmedEvent() { + fixture.given(new OrderCreatedEvent(ORDER_ID)) + .when(new ConfirmOrderCommand(ORDER_ID)) + .expectEvents(new OrderConfirmedEvent(ORDER_ID)); + } + + @Test + void givenOrderCreatedEventAndOrderConfirmedEvent_whenConfirmOrderCommand_thenExpectNoEvents() { + fixture.given(new OrderCreatedEvent(ORDER_ID), new OrderConfirmedEvent(ORDER_ID)) + .when(new ConfirmOrderCommand(ORDER_ID)) + .expectNoEvents(); + } + + @Test + void givenOrderCreatedEvent_whenShipOrderCommand_thenShouldThrowUnconfirmedOrderException() { + fixture.given(new OrderCreatedEvent(ORDER_ID)) + .when(new ShipOrderCommand(ORDER_ID)) .expectException(UnconfirmedOrderException.class); } @Test - public void givenOrderPlacedEventAndOrderConfirmedEvent_whenShipOrderCommand_thenShouldPublishOrderShippedEvent() { - String orderId = UUID.randomUUID().toString(); - String product = "Deluxe Chair"; - fixture.given(new OrderPlacedEvent(orderId, product), new OrderConfirmedEvent(orderId)) - .when(new ShipOrderCommand(orderId)) - .expectEvents(new OrderShippedEvent(orderId)); + void givenOrderCreatedEventAndOrderConfirmedEvent_whenShipOrderCommand_thenShouldPublishOrderShippedEvent() { + fixture.given(new OrderCreatedEvent(ORDER_ID), new OrderConfirmedEvent(ORDER_ID)) + .when(new ShipOrderCommand(ORDER_ID)) + .expectEvents(new OrderShippedEvent(ORDER_ID)); } + @Test + void givenOrderCreatedEventProductAndOrderConfirmedEvent_whenAddProductCommand_thenShouldThrowOrderAlreadyConfirmedException() { + fixture.given(new OrderCreatedEvent(ORDER_ID), new OrderConfirmedEvent(ORDER_ID)) + .when(new AddProductCommand(ORDER_ID, PRODUCT_ID)) + .expectException(OrderAlreadyConfirmedException.class) + .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID))); + } + + @Test + void givenOrderCreatedEventProductAddedEventAndOrderConfirmedEvent_whenIncrementProductCountCommand_thenShouldThrowOrderAlreadyConfirmedException() { + fixture.given(new OrderCreatedEvent(ORDER_ID), + new ProductAddedEvent(ORDER_ID, PRODUCT_ID), + new OrderConfirmedEvent(ORDER_ID)) + .when(new IncrementProductCountCommand(ORDER_ID, PRODUCT_ID)) + .expectException(OrderAlreadyConfirmedException.class) + .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID))); + } + + @Test + void givenOrderCreatedEventProductAddedEventAndOrderConfirmedEvent_whenDecrementProductCountCommand_thenShouldThrowOrderAlreadyConfirmedException() { + fixture.given(new OrderCreatedEvent(ORDER_ID), + new ProductAddedEvent(ORDER_ID, PRODUCT_ID), + new OrderConfirmedEvent(ORDER_ID)) + .when(new DecrementProductCountCommand(ORDER_ID, PRODUCT_ID)) + .expectException(OrderAlreadyConfirmedException.class) + .expectExceptionMessage(Matchers.predicate(message -> ((String) message).contains(ORDER_ID))); + } } \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java new file mode 100644 index 0000000000..a4189df31d --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/CustomInterruptedException.java @@ -0,0 +1,10 @@ +package com.baeldung.concurrent.interrupt; + +public class CustomInterruptedException extends Exception { + + private static final long serialVersionUID = 1L; + + CustomInterruptedException(String message) { + super(message); + } +} diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java new file mode 100644 index 0000000000..7d81769854 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/interrupt/InterruptExample.java @@ -0,0 +1,47 @@ +package com.baeldung.concurrent.interrupt; + +public class InterruptExample extends Thread { + + public static void propagateException() throws InterruptedException { + Thread.sleep(1000); + Thread.currentThread().interrupt(); + if (Thread.interrupted()) { + throw new InterruptedException(); + } + } + + public static Boolean restoreTheState() { + InterruptExample thread1 = new InterruptExample(); + thread1.start(); + thread1.interrupt(); + return thread1.isInterrupted(); + } + + public void run() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + public static void throwCustomException() throws Exception { + + Thread.sleep(1000); + Thread.currentThread().interrupt(); + if (Thread.interrupted()) { + throw new CustomInterruptedException("This thread was interrupted"); + } + } + + public static Boolean handleWithCustomException() throws CustomInterruptedException{ + try { + Thread.sleep(1000); + Thread.currentThread().interrupt(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new CustomInterruptedException("This thread was interrupted..."); + } + return Thread.currentThread().isInterrupted(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java new file mode 100644 index 0000000000..1ea3f9aa9b --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/test/java/com/baeldung/concurrent/interrupt/InterruptExampleUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.concurrent.interrupt; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class InterruptExampleUnitTest { + + @Test + public void whenPropagateException_thenThrowsInterruptedException() { + assertThrows(InterruptedException.class, () -> InterruptExample.propagateException()); + } + + @Test + public void whenRestoreTheState_thenReturnsTrue() { + assertTrue(InterruptExample.restoreTheState()); + } + + @Test + public void whenThrowCustomException_thenContainsExpectedMessage() { + Exception exception = assertThrows(CustomInterruptedException.class, () -> InterruptExample.throwCustomException()); + String expectedMessage = "This thread was interrupted"; + String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessage)); + } + + @Test + public void whenHandleWithCustomException_thenReturnsTrue() throws CustomInterruptedException{ + assertTrue(InterruptExample.handleWithCustomException()); + } +} diff --git a/core-java-modules/core-java-console/pom.xml b/core-java-modules/core-java-console/pom.xml index 1d58d8c253..fc4f1875ca 100644 --- a/core-java-modules/core-java-console/pom.xml +++ b/core-java-modules/core-java-console/pom.xml @@ -45,7 +45,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} java com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed @@ -105,7 +104,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} run-benchmarks @@ -134,7 +132,6 @@ 3.0.0-M1 - 1.6.0 1.8 1.8 diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml index 0968536e65..02b5adae7c 100644 --- a/core-java-modules/core-java-io/pom.xml +++ b/core-java-modules/core-java-io/pom.xml @@ -60,7 +60,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} java com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed @@ -108,7 +107,6 @@ org.codehaus.mojo exec-maven-plugin - run-benchmarks diff --git a/core-java-modules/core-java-jar/pom.xml b/core-java-modules/core-java-jar/pom.xml index 6e9d713d7c..45500de739 100644 --- a/core-java-modules/core-java-jar/pom.xml +++ b/core-java-modules/core-java-jar/pom.xml @@ -189,7 +189,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} java com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed @@ -249,7 +248,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} run-benchmarks @@ -397,7 +395,6 @@ 1.4.4 3.1.1 2.0.3.RELEASE - 1.6.0 1.8 1.8 diff --git a/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml index fd59c151e6..f80d7d4815 100644 --- a/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml +++ b/core-java-modules/core-java-jpms/decoupling-pattern1/pom.xml @@ -6,9 +6,15 @@ 4.0.0 com.baeldung.decoupling-pattern1 decoupling-pattern1 - 1.0 + 1.0-SNAPSHOT pom + + com.baeldung.core-java-modules + core-java-jpms + 0.0.1-SNAPSHOT + + servicemodule consumermodule diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml index 816f5cf9e8..c7bff60a8b 100644 --- a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml @@ -32,6 +32,11 @@ org.apache.maven.plugins maven-compiler-plugin + ${compiler.plugin.version} + + ${source.version} + ${target.version} + diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml index 17bca54edb..91b92b9df5 100644 --- a/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/pom.xml @@ -9,6 +9,12 @@ 1.0-SNAPSHOT pom + + com.baeldung.core-java-modules + core-java-jpms + 0.0.1-SNAPSHOT + + servicemodule providermodule diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml index 1e29df7053..6c0f1956b9 100644 --- a/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/providermodule/pom.xml @@ -17,7 +17,7 @@ com.baeldung.servicemodule - servicemodule2 + servicemodule ${servicemodule.version} @@ -27,6 +27,11 @@ org.apache.maven.plugins maven-compiler-plugin + ${compiler.plugin.version} + + ${source.version} + ${target.version} + diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml index 9a687c9ae7..50201911a6 100644 --- a/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/servicemodule/pom.xml @@ -19,6 +19,11 @@ org.apache.maven.plugins maven-compiler-plugin + ${compiler.plugin.version} + + ${source.version} + ${target.version} + diff --git a/core-java-modules/core-java-jpms/pom.xml b/core-java-modules/core-java-jpms/pom.xml index 5809c0f579..ee7eb02f10 100644 --- a/core-java-modules/core-java-jpms/pom.xml +++ b/core-java-modules/core-java-jpms/pom.xml @@ -20,4 +20,26 @@ decoupling-pattern2 + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${compiler.plugin.version} + + ${source.version} + ${target.version} + + + + + + + + 3.8.0 + 11 + 11 + + diff --git a/core-java-modules/core-java-lang-4/README.md b/core-java-modules/core-java-lang-4/README.md index 77d14f0fc8..8e8d6185b0 100644 --- a/core-java-modules/core-java-lang-4/README.md +++ b/core-java-modules/core-java-lang-4/README.md @@ -3,3 +3,4 @@ This module contains articles about core features in the Java language - [The Java final Keyword – Impact on Performance](https://www.baeldung.com/java-final-performance) +- [The package-info.java File](https://www.baeldung.com/java-package-info) diff --git a/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/finalkeyword/package-info.java b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/finalkeyword/package-info.java new file mode 100644 index 0000000000..fd1e3cf8d8 --- /dev/null +++ b/core-java-modules/core-java-lang-4/src/main/java/com/baeldung/finalkeyword/package-info.java @@ -0,0 +1,13 @@ +/** +* This module is about impact of the final keyword on performance + *

+ * This module explores if there are any performance benefits from + * using the final keyword in our code. This module examines the performance + * implications of using final on a variable, method, and class level. + *

+* +* @since 1.0 +* @author baeldung +* @version 1.1 +*/ +package com.baeldung.finalkeyword; diff --git a/core-java-modules/core-java-lang-math-2/pom.xml b/core-java-modules/core-java-lang-math-2/pom.xml index 42704c784a..56e18158b3 100644 --- a/core-java-modules/core-java-lang-math-2/pom.xml +++ b/core-java-modules/core-java-lang-math-2/pom.xml @@ -62,18 +62,6 @@ - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - - 3.6.1 3.9.0 diff --git a/core-java-modules/core-java-nio-2/README.md b/core-java-modules/core-java-nio-2/README.md index ef73159f66..ab54899501 100644 --- a/core-java-modules/core-java-nio-2/README.md +++ b/core-java-modules/core-java-nio-2/README.md @@ -9,4 +9,5 @@ This module contains articles about core Java non-blocking input and output (IO) - [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector) - [Using Java MappedByteBuffer](https://www.baeldung.com/java-mapped-byte-buffer) - [How to Lock a File in Java](https://www.baeldung.com/java-lock-files) +- [Java NIO DatagramChannel](https://www.baeldung.com/java-nio-datagramchannel) - [[<-- Prev]](/core-java-modules/core-java-nio) diff --git a/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramChannelBuilder.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramChannelBuilder.java new file mode 100644 index 0000000000..43e0747622 --- /dev/null +++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramChannelBuilder.java @@ -0,0 +1,18 @@ +package com.baeldung.datagramchannel; + +import java.io.IOException; +import java.net.SocketAddress; +import java.nio.channels.DatagramChannel; + +public class DatagramChannelBuilder { + + public static DatagramChannel openChannel() throws IOException { + DatagramChannel datagramChannel = DatagramChannel.open(); + return datagramChannel; + } + + public static DatagramChannel bindChannel(SocketAddress local) throws IOException { + return openChannel().bind(local); + } + +} diff --git a/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramClient.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramClient.java new file mode 100644 index 0000000000..e377cc431c --- /dev/null +++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramClient.java @@ -0,0 +1,31 @@ +package com.baeldung.datagramchannel; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; + +public class DatagramClient { + + public static DatagramChannel startClient() throws IOException { + DatagramChannel client = DatagramChannelBuilder.bindChannel(null); + client.configureBlocking(false); + return client; + } + + public static void sendMessage(DatagramChannel client, String msg, SocketAddress serverAddress) throws IOException { + ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes()); + client.send(buffer, serverAddress); + } + + public static void main(String[] args) throws IOException { + DatagramChannel client = startClient(); + String msg = "Hello, this is a Baeldung's DatagramChannel based UDP client!"; + InetSocketAddress serverAddress = new InetSocketAddress("localhost", 7001); + + sendMessage(client, msg, serverAddress); + + } + +} diff --git a/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramServer.java b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramServer.java new file mode 100644 index 0000000000..ed3345a26d --- /dev/null +++ b/core-java-modules/core-java-nio-2/src/main/java/com/baeldung/datagramchannel/DatagramServer.java @@ -0,0 +1,46 @@ +package com.baeldung.datagramchannel; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; + +public class DatagramServer { + + public static DatagramChannel startServer() throws IOException { + InetSocketAddress address = new InetSocketAddress("localhost", 7001); + DatagramChannel server = DatagramChannelBuilder.bindChannel(address); + + System.out.println("Server started at #" + address); + + return server; + } + + public static String receiveMessage(DatagramChannel server) throws IOException { + ByteBuffer buffer = ByteBuffer.allocate(1024); + SocketAddress remoteAdd = server.receive(buffer); + String message = extractMessage(buffer); + + System.out.println("Client at #" + remoteAdd + " sent: " + message); + + return message; + } + + private static String extractMessage(ByteBuffer buffer) { + buffer.flip(); + + byte[] bytes = new byte[buffer.remaining()]; + buffer.get(bytes); + + String msg = new String(bytes); + + return msg; + } + + public static void main(String[] args) throws IOException { + DatagramChannel server = startServer(); + receiveMessage(server); + } + +} diff --git a/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/datagramchannel/DatagramChannelUnitTest.java b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/datagramchannel/DatagramChannelUnitTest.java new file mode 100644 index 0000000000..f816072ee7 --- /dev/null +++ b/core-java-modules/core-java-nio-2/src/test/java/com/baeldung/datagramchannel/DatagramChannelUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.datagramchannel; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.DatagramChannel; +import org.junit.jupiter.api.Test; + +public class DatagramChannelUnitTest { + + @Test + public void whenClientSendsAndServerReceivesUDPPacket_thenCorrect() throws IOException { + DatagramChannel server = DatagramServer.startServer(); + DatagramChannel client = DatagramClient.startClient(); + + String msg1 = "Hello, this is a Baeldung's DatagramChannel based UDP client!"; + String msg2 = "Hi again!, Are you there!"; + + InetSocketAddress serverAddress = new InetSocketAddress("localhost", 7001); + + DatagramClient.sendMessage(client, msg1, serverAddress); + DatagramClient.sendMessage(client, msg2, serverAddress); + + assertEquals("Hello, this is a Baeldung's DatagramChannel based UDP client!", DatagramServer.receiveMessage(server)); + assertEquals("Hi again!, Are you there!", DatagramServer.receiveMessage(server)); + } + +} diff --git a/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java index 69b65852cc..cb5a20f184 100644 --- a/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java @@ -101,7 +101,8 @@ class ProcessUnderstandingUnitTest { .replace("/", File.separator)); BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream())); - int value = Integer.parseInt(output.readLine()); + String line = output.readLine(); + int value = Integer.parseInt(line); assertEquals(3, value); } diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md index 3f9520b888..684f2504cc 100644 --- a/core-java-modules/core-java-security-2/README.md +++ b/core-java-modules/core-java-security-2/README.md @@ -16,4 +16,5 @@ This module contains articles about core Java Security - [Java AES Encryption and Decryption](https://www.baeldung.com/java-aes-encryption-decryption) - [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception) - [The java.security.egd JVM Option](https://www.baeldung.com/java-security-egd) +- [RSA in Java](https://www.baeldung.com/java-rsa) - More articles: [[<-- prev]](/core-java-modules/core-java-security) diff --git a/core-java-modules/core-java-streams-3/README.md b/core-java-modules/core-java-streams-3/README.md index f81dca485b..26b4dfe975 100644 --- a/core-java-modules/core-java-streams-3/README.md +++ b/core-java-modules/core-java-streams-3/README.md @@ -11,4 +11,5 @@ This module contains articles about the Stream API in Java. - [Add BigDecimals using the Stream API](https://www.baeldung.com/java-stream-add-bigdecimals) - [Should We Close a Java Stream?](https://www.baeldung.com/java-stream-close) - [Returning Stream vs. Collection](https://www.baeldung.com/java-return-stream-collection) +- [Convert a Java Enumeration Into a Stream](https://www.baeldung.com/java-enumeration-to-stream) - More articles: [[<-- prev>]](/../core-java-streams-2) diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/conversion/EnumerationSpliterator.java b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/conversion/EnumerationSpliterator.java new file mode 100644 index 0000000000..5227fcb6c4 --- /dev/null +++ b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/conversion/EnumerationSpliterator.java @@ -0,0 +1,30 @@ +package com.baeldung.streams.conversion; + +import java.util.Enumeration; +import java.util.Spliterators.AbstractSpliterator; +import java.util.function.Consumer; + +public class EnumerationSpliterator extends AbstractSpliterator { + + private final Enumeration enumeration; + + public EnumerationSpliterator(long est, int additionalCharacteristics, Enumeration enumeration) { + super(est, additionalCharacteristics); + this.enumeration = enumeration; + } + + @Override + public boolean tryAdvance(Consumer action) { + if (enumeration.hasMoreElements()) { + action.accept(enumeration.nextElement()); + return true; + } + return false; + } + + @Override + public void forEachRemaining(Consumer action) { + while (enumeration.hasMoreElements()) + action.accept(enumeration.nextElement()); + } +} diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/conversion/EnumerationStreamConversion.java b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/conversion/EnumerationStreamConversion.java new file mode 100644 index 0000000000..cf041b9426 --- /dev/null +++ b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/conversion/EnumerationStreamConversion.java @@ -0,0 +1,16 @@ +package com.baeldung.streams.conversion; + +import java.util.Enumeration; +import java.util.Spliterator; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class EnumerationStreamConversion { + + public static Stream convert(Enumeration enumeration) { + EnumerationSpliterator spliterator = new EnumerationSpliterator(Long.MAX_VALUE, Spliterator.ORDERED, enumeration); + Stream stream = StreamSupport.stream(spliterator, false); + + return stream; + } +} diff --git a/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/conversion/EnumerationStreamConversionUnitTest.java b/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/conversion/EnumerationStreamConversionUnitTest.java new file mode 100644 index 0000000000..a075312fb5 --- /dev/null +++ b/core-java-modules/core-java-streams-3/src/test/java/com/baeldung/streams/conversion/EnumerationStreamConversionUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.streams.conversion; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; + +import java.util.Arrays; +import java.util.List; +import java.util.Vector; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class EnumerationStreamConversionUnitTest { + + @Test + public void givenEnumeration_whenConvertedToStream_thenNotNull() { + Vector input = new Vector<>(Arrays.asList(1, 2, 3, 4, 5)); + + Stream resultingStream = EnumerationStreamConversion.convert(input.elements()); + + Assert.assertNotNull(resultingStream); + } + + @Test + public void whenConvertedToList_thenCorrect() { + Vector input = new Vector<>(Arrays.asList(1, 2, 3, 4, 5)); + + Stream stream = EnumerationStreamConversion.convert(input.elements()); + List list = stream.filter(e -> e >= 3) + .collect(Collectors.toList()); + assertThat(list, contains(3, 4, 5)); + } +} diff --git a/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/splitstringbynewline/SplitStringByNewLineUnitTest.java b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/splitstringbynewline/SplitStringByNewLineUnitTest.java new file mode 100644 index 0000000000..9afba62947 --- /dev/null +++ b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/splitstringbynewline/SplitStringByNewLineUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.splitstringbynewline; + +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class SplitStringByNewLineUnitTest { + @Test + public void givenString_whenSplitByNewLineUsingSystemLineSeparator_thenReturnsArray() { + assertThat("Line1\nLine2\nLine3".split(System.lineSeparator())).containsExactly("Line1", "Line2", "Line3"); + } + + @Test + public void givenString_whenSplitByNewLineUsingRegularExpressionPattern_thenReturnsArray() { + assertThat("Line1\nLine2\nLine3".split("\\r?\\n|\\r")).containsExactly("Line1", "Line2", "Line3"); + + assertThat("Line1\rLine2\rLine3".split("\\r?\\n|\\r")).containsExactly("Line1", "Line2", "Line3"); + + assertThat("Line1\r\nLine2\r\nLine3".split("\\r?\\n|\\r")).containsExactly("Line1", "Line2", "Line3"); + } + + @Test + public void givenString_whenSplitByNewLineUsingJava8Pattern_thenReturnsArray() { + assertThat("Line1\nLine2\nLine3".split("\\R")).containsExactly("Line1", "Line2", "Line3"); + + assertThat("Line1\rLine2\rLine3".split("\\R")).containsExactly("Line1", "Line2", "Line3"); + + assertThat("Line1\r\nLine2\r\nLine3".split("\\R")).containsExactly("Line1", "Line2", "Line3"); + } +} diff --git a/core-java-modules/core-java-sun/pom.xml b/core-java-modules/core-java-sun/pom.xml index 0f53407ec1..541af2445f 100644 --- a/core-java-modules/core-java-sun/pom.xml +++ b/core-java-modules/core-java-sun/pom.xml @@ -44,7 +44,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} java com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed @@ -68,7 +67,6 @@ org.codehaus.mojo exec-maven-plugin - run-benchmarks diff --git a/core-java-modules/core-java/pom.xml b/core-java-modules/core-java/pom.xml index b8d75058eb..9b595288e6 100644 --- a/core-java-modules/core-java/pom.xml +++ b/core-java-modules/core-java/pom.xml @@ -94,7 +94,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} java com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed @@ -154,7 +153,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} run-benchmarks @@ -193,7 +191,6 @@ 1.1 3.0.0-M1 - 1.6.0 1.8 1.8 diff --git a/data-structures/pom.xml b/data-structures/pom.xml index e2d2e23090..7bf34b1c63 100644 --- a/data-structures/pom.xml +++ b/data-structures/pom.xml @@ -35,7 +35,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} diff --git a/discord4j/pom.xml b/discord4j/pom.xml index 664692f60a..07fa3fa72e 100644 --- a/discord4j/pom.xml +++ b/discord4j/pom.xml @@ -2,21 +2,18 @@ 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.3.5.RELEASE - - com.baeldung - discord4j-bot + discord4j 0.0.1-SNAPSHOT - discord4j-bot + discord4j Demo Discord bot using Discord4J + Spring Boot - - 1.8 - + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + @@ -67,5 +64,9 @@ + + + 1.8 + diff --git a/docker/docker-spring-boot-postgres/pom.xml b/docker/docker-spring-boot-postgres/pom.xml index 0b359138f6..d08ae130db 100644 --- a/docker/docker-spring-boot-postgres/pom.xml +++ b/docker/docker-spring-boot-postgres/pom.xml @@ -2,21 +2,18 @@ 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.4.0 - - com.baeldung.docker docker-spring-boot-postgres 0.0.1-SNAPSHOT docker-spring-boot-postgres Demo project showing Spring Boot, PostgreSQL, and Docker - - - 11 - + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + @@ -44,5 +41,9 @@ + + + 11 + \ No newline at end of file diff --git a/docker/pom.xml b/docker/pom.xml index f05c303938..3fcc9ca94f 100644 --- a/docker/pom.xml +++ b/docker/pom.xml @@ -4,19 +4,19 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.3.1.RELEASE - - - com.baeldung.docker docker 0.0.1 docker Demo project showing Spring Boot and Docker pom + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + 11 diff --git a/jhipster-5/bookstore-monolith/pom.xml b/jhipster-5/bookstore-monolith/pom.xml index 5da3bde449..8403c2d1d4 100644 --- a/jhipster-5/bookstore-monolith/pom.xml +++ b/jhipster-5/bookstore-monolith/pom.xml @@ -6,7 +6,7 @@ bookstore-monolith 0.0.1-SNAPSHOT war - Bookstore + bookstore-monolith jhipster-5 diff --git a/jhipster/jhipster-uaa/gateway/pom.xml b/jhipster/jhipster-uaa/gateway/pom.xml index 21a04a9692..53422bfa44 100644 --- a/jhipster/jhipster-uaa/gateway/pom.xml +++ b/jhipster/jhipster-uaa/gateway/pom.xml @@ -4,7 +4,7 @@ com.baeldung.jhipster.gateway gateway 0.0.1-SNAPSHOT - Gateway + gateway war diff --git a/jhipster/jhipster-uaa/quotes/pom.xml b/jhipster/jhipster-uaa/quotes/pom.xml index 12bbf66d37..2d61a2a820 100644 --- a/jhipster/jhipster-uaa/quotes/pom.xml +++ b/jhipster/jhipster-uaa/quotes/pom.xml @@ -4,7 +4,7 @@ com.baeldung.jhipster.quotes quotes 0.0.1-SNAPSHOT - Quotes + quotes war diff --git a/jhipster/jhipster-uaa/uaa/pom.xml b/jhipster/jhipster-uaa/uaa/pom.xml index d0d81aa0b3..cabbf1de33 100644 --- a/jhipster/jhipster-uaa/uaa/pom.xml +++ b/jhipster/jhipster-uaa/uaa/pom.xml @@ -4,7 +4,7 @@ com.baeldung.jhipster.uaa uaa 0.0.1-SNAPSHOT - Uaa + uaa war diff --git a/kubernetes/k8s-intro/pom.xml b/kubernetes/k8s-intro/pom.xml index 4a5bb09711..5b4867d0df 100644 --- a/kubernetes/k8s-intro/pom.xml +++ b/kubernetes/k8s-intro/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.baeldung - kubernetes-parent + kubernetes 1.0.0-SNAPSHOT k8s-intro diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPods.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPods.java new file mode 100644 index 0000000000..7df972b738 --- /dev/null +++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPods.java @@ -0,0 +1,72 @@ +package com.baeldung.kubernetes.intro; + +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.reflect.TypeToken; + +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Pod; +import io.kubernetes.client.util.Config; +import io.kubernetes.client.util.Watch; +import io.kubernetes.client.util.Watch.Response; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; + +public class WatchPods { + + private static Logger log = LoggerFactory.getLogger(WatchPods.class); + + public static void main(String[] args) throws Exception { + + ApiClient client = Config.defaultClient(); + + // Optional, put helpful during tests: disable client timeout and enable + // HTTP wire-level logs + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> log.info(message)); + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + OkHttpClient newClient = client.getHttpClient() + .newBuilder() + .addInterceptor(interceptor) + .readTimeout(0, TimeUnit.SECONDS) + .build(); + + client.setHttpClient(newClient); + CoreV1Api api = new CoreV1Api(client); + + // Create the watch object that monitors pod creation/deletion/update events + while (true) { + log.info("[I46] Creating watch..."); + try (Watch watch = Watch.createWatch( + client, + api.listPodForAllNamespacesCall(false, null, null, null, null, "false", null, null, 10, true, null), + new TypeToken>(){}.getType())) { + + log.info("[I52] Receiving events:"); + for (Response event : watch) { + V1Pod pod = event.object; + V1ObjectMeta meta = pod.getMetadata(); + switch (event.type) { + case "ADDED": + case "MODIFIED": + case "DELETED": + log.info("event.type: {}, namespace={}, name={}", + event.type, + meta.getNamespace(), + meta.getName()); + break; + default: + log.warn("[W66] Unknown event type: {}", event.type); + } + } + } catch (ApiException ex) { + log.error("[E70] ApiError", ex); + } + } + } +} diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPodsUsingBookmarks.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPodsUsingBookmarks.java new file mode 100644 index 0000000000..9dfccfec08 --- /dev/null +++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPodsUsingBookmarks.java @@ -0,0 +1,87 @@ +package com.baeldung.kubernetes.intro; + +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.reflect.TypeToken; + +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Pod; +import io.kubernetes.client.openapi.models.V1PodList; +import io.kubernetes.client.util.Config; +import io.kubernetes.client.util.Watch; +import io.kubernetes.client.util.Watch.Response; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; + +public class WatchPodsUsingBookmarks { + + private static Logger log = LoggerFactory.getLogger(WatchPodsUsingBookmarks.class); + + public static void main(String[] args) throws Exception { + + ApiClient client = Config.defaultClient(); + + // Optional, put helpful during tests: disable client timeout and enable + // HTTP wire-level logs + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> log.info(message)); + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + OkHttpClient newClient = client.getHttpClient() + .newBuilder() + .addInterceptor(interceptor) + .readTimeout(0, TimeUnit.SECONDS) + .build(); + + client.setHttpClient(newClient); + CoreV1Api api = new CoreV1Api(client); + + String resourceVersion = null; + while (true) { + // Get a fresh list only we need to resync + if ( resourceVersion == null ) { + log.info("[I48] Creating initial POD list..."); + V1PodList podList = api.listPodForAllNamespaces(true, null, null, null, null, "false", resourceVersion, null, null, null); + resourceVersion = podList.getMetadata().getResourceVersion(); + } + + while (true) { + log.info("[I54] Creating watch: resourceVersion={}", resourceVersion); + try (Watch watch = Watch.createWatch( + client, + api.listPodForAllNamespacesCall(true, null, null, null, null, "false", resourceVersion, null, 10, true, null), + new TypeToken>(){}.getType())) { + + log.info("[I60] Receiving events:"); + for (Response event : watch) { + V1Pod pod = event.object; + V1ObjectMeta meta = pod.getMetadata(); + switch (event.type) { + case "BOOKMARK": + resourceVersion = meta.getResourceVersion(); + log.info("[I67] event.type: {}, resourceVersion={}", event.type,resourceVersion); + break; + case "ADDED": + case "MODIFIED": + case "DELETED": + log.info("event.type: {}, namespace={}, name={}", + event.type, + meta.getNamespace(), + meta.getName()); + break; + default: + log.warn("[W76] Unknown event type: {}", event.type); + } + } + } catch (ApiException ex) { + log.error("[E80] ApiError", ex); + resourceVersion = null; + } + } + } + } +} diff --git a/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPodsUsingResourceVersions.java b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPodsUsingResourceVersions.java new file mode 100644 index 0000000000..2165d7fc0b --- /dev/null +++ b/kubernetes/k8s-intro/src/main/java/com/baeldung/kubernetes/intro/WatchPodsUsingResourceVersions.java @@ -0,0 +1,111 @@ +package com.baeldung.kubernetes.intro; + +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Pod; +import io.kubernetes.client.openapi.models.V1PodList; +import io.kubernetes.client.util.Config; +import io.kubernetes.client.util.Watch; +import io.kubernetes.client.util.Watch.Response; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; + +public class WatchPodsUsingResourceVersions { + + private static Logger log = LoggerFactory.getLogger(WatchPodsUsingResourceVersions.class); + + public static void main(String[] args) throws Exception { + + ApiClient client = Config.defaultClient(); + + // Optional, put helpful during tests: disable client timeout and enable + // HTTP wire-level logs + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> log.info(message)); + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + OkHttpClient newClient = client.getHttpClient() + .newBuilder() + .addInterceptor(interceptor) + .readTimeout(0, TimeUnit.SECONDS) + .build(); + + client.setHttpClient(newClient); + CoreV1Api api = new CoreV1Api(client); + + String resourceVersion = null; + while (true) { + try { + if ( resourceVersion == null ) { + V1PodList podList = api.listPodForAllNamespaces(null, null, null, null, null, null, resourceVersion, null, null, null); + resourceVersion = podList.getMetadata().getResourceVersion(); + } + + log.info("[I59] Creating watch: resourceVersion={}", resourceVersion); + try (Watch watch = Watch.createWatch( + client, + api.listPodForAllNamespacesCall(null, null, null, null, null, null, resourceVersion, null, 60, true, null), + new TypeToken>(){}.getType())) { + + log.info("[I65] Receiving events:"); + for (Response event : watch) { + V1Pod pod = event.object; + V1ObjectMeta meta = pod.getMetadata(); + switch (event.type) { + case "ADDED": + case "MODIFIED": + case "DELETED": + log.info("event: type={}, namespace={}, name={}", + event.type, + meta.getNamespace(), + meta.getName()); + break; + default: + log.warn("[W76] Unknown event type: {}", event.type); + } + } + } + } + catch (ApiException ex) { + if ( ex.getCode() == 504 || ex.getCode() == 410 ) { + resourceVersion = extractResourceVersionFromException(ex); + } + else { + // Reset resource version + resourceVersion = null; + } + } + } + } + + private static String extractResourceVersionFromException(ApiException ex) { + + String body = ex.getResponseBody(); + if (body == null) { + return null; + } + + Gson gson = new Gson(); + Map st = gson.fromJson(body, Map.class); + Pattern p = Pattern.compile("Timeout: Too large resource version: (\\d+), current: (\\d+)"); + String msg = (String)st.get("message"); + Matcher m = p.matcher(msg); + if (!m.matches()) { + return null; + } + + return m.group(2); + } + +} diff --git a/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsLiveTest.java b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsLiveTest.java new file mode 100644 index 0000000000..37828d7a2d --- /dev/null +++ b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsLiveTest.java @@ -0,0 +1,10 @@ +package com.baeldung.kubernetes.intro; + +import org.junit.jupiter.api.Test; + +class WatchPodsLiveTest { + @Test + void whenWatchPods_thenSuccess() throws Exception { + WatchPods.main(new String[] {}); + } +} diff --git a/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsUsingBookmarksLiveTest.java b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsUsingBookmarksLiveTest.java new file mode 100644 index 0000000000..ea111f22a2 --- /dev/null +++ b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsUsingBookmarksLiveTest.java @@ -0,0 +1,10 @@ +package com.baeldung.kubernetes.intro; + +import org.junit.jupiter.api.Test; + +class WatchPodsUsingBookmarksLiveTest { + @Test + void whenWatchPods_thenSuccess() throws Exception { + WatchPodsUsingBookmarks.main(new String[] {}); + } +} diff --git a/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsUsingResourceVersionsLiveTest.java b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsUsingResourceVersionsLiveTest.java new file mode 100644 index 0000000000..79c3a13eb2 --- /dev/null +++ b/kubernetes/k8s-intro/src/test/java/com/baeldung/kubernetes/intro/WatchPodsUsingResourceVersionsLiveTest.java @@ -0,0 +1,10 @@ +package com.baeldung.kubernetes.intro; + +import org.junit.jupiter.api.Test; + +class WatchPodsUsingResourceVersionsLiveTest { + @Test + void whenWatchPods_thenSuccess() throws Exception { + WatchPodsUsingResourceVersions.main(new String[] {}); + } +} diff --git a/kubernetes/pom.xml b/kubernetes/pom.xml index fe10295e44..aea3dea47e 100644 --- a/kubernetes/pom.xml +++ b/kubernetes/pom.xml @@ -5,7 +5,7 @@ parent-modules 1.0.0-SNAPSHOT - kubernetes-parent + kubernetes pom k8s-intro diff --git a/libraries-3/pom.xml b/libraries-3/pom.xml index 2f6e9fa747..3d3b5db890 100644 --- a/libraries-3/pom.xml +++ b/libraries-3/pom.xml @@ -189,7 +189,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} start-server @@ -229,7 +228,6 @@ 4.4.13 4.5.12 2.2 - 1.6.0 0.3.0 2.8 2.1.3 diff --git a/libraries-concurrency/pom.xml b/libraries-concurrency/pom.xml index b7dc5187b1..66296d829f 100644 --- a/libraries-concurrency/pom.xml +++ b/libraries-concurrency/pom.xml @@ -47,7 +47,6 @@ org.codehaus.mojo exec-maven-plugin - 1.6.0 com.baeldung.quasar.App target/classes diff --git a/micronaut/pom.xml b/micronaut/pom.xml index d6df6a0347..bd0022c9e1 100644 --- a/micronaut/pom.xml +++ b/micronaut/pom.xml @@ -102,7 +102,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec.plugin.version} java @@ -146,7 +145,6 @@ 1.2.3 3.1.6.RELEASE 3.7.0 - 1.6.0 3.1.0 diff --git a/netflix-modules/genie/pom.xml b/netflix-modules/genie/pom.xml index 2c7c04b26b..c68ecac7a2 100644 --- a/netflix-modules/genie/pom.xml +++ b/netflix-modules/genie/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 genie - Genie + genie jar Sample project for Netflix Genie diff --git a/netflix-modules/mantis/pom.xml b/netflix-modules/mantis/pom.xml index 5d9611ccdf..3f75d448e4 100644 --- a/netflix-modules/mantis/pom.xml +++ b/netflix-modules/mantis/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 mantis - Mantis + mantis jar Sample project for Netflix Mantis diff --git a/netflix-modules/pom.xml b/netflix-modules/pom.xml index 538126fb34..4031d007f8 100644 --- a/netflix-modules/pom.xml +++ b/netflix-modules/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 netflix-modules - Netflix Modules + netflix-modules pom Module for Netflix projects diff --git a/persistence-modules/hibernate-annotations/README.md b/persistence-modules/hibernate-annotations/README.md index 393cf82bfd..7d7740a069 100644 --- a/persistence-modules/hibernate-annotations/README.md +++ b/persistence-modules/hibernate-annotations/README.md @@ -8,3 +8,4 @@ This module contains articles about Annotations used in Hibernate. - [Difference Between @JoinColumn and mappedBy](https://www.baeldung.com/jpa-joincolumn-vs-mappedby) - [Hibernate One to Many Annotation Tutorial](https://www.baeldung.com/hibernate-one-to-many) - [Hibernate @WhereJoinTable Annotation](https://www.baeldung.com/hibernate-wherejointable) +- [Usage of the Hibernate @LazyCollection Annotation](https://www.baeldung.com/hibernate-lazycollection) diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/lazycollection/model/Branch.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/lazycollection/model/Branch.java new file mode 100644 index 0000000000..de88647546 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/lazycollection/model/Branch.java @@ -0,0 +1,103 @@ +package com.baeldung.hibernate.lazycollection.model; + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OrderColumn; +import javax.persistence.OneToMany; +import javax.persistence.Entity; +import java.util.ArrayList; +import java.util.List; + +@Entity +public class Branch { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + public Branch() { + } + public Branch(String name) { + this.name = name; + } + + @OneToMany(mappedBy = "mainBranch") + @LazyCollection(LazyCollectionOption.TRUE) + private List mainEmployees; + + @OneToMany(mappedBy = "subBranch") + @LazyCollection(LazyCollectionOption.FALSE) + private List subEmployees; + + @OneToMany(mappedBy = "additionalBranch") + @LazyCollection(LazyCollectionOption.EXTRA) + @OrderColumn(name = "order_id") + private List additionalEmployees; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getMainEmployees() { + return mainEmployees; + } + + public void setMainEmployees(List mainEmployees) { + this.mainEmployees = mainEmployees; + } + + public List getSubEmployees() { + return subEmployees; + } + + public void setSubEmployees(List subEmployees) { + this.subEmployees = subEmployees; + } + + public List getAdditionalEmployees() { + return additionalEmployees; + } + + public void setAdditionalEmployees(List additionalEmployees) { + this.additionalEmployees = additionalEmployees; + } + + public void addMainEmployee(Employee employee) { + if (this.mainEmployees == null) { + this.mainEmployees = new ArrayList<>(); + } + this.mainEmployees.add(employee); + } + + public void addSubEmployee(Employee employee) { + if (this.subEmployees == null) { + this.subEmployees = new ArrayList<>(); + } + this.subEmployees.add(employee); + } + + public void addAdditionalEmployee(Employee employee) { + if (this.additionalEmployees == null) { + this.additionalEmployees = new ArrayList<>(); + } + this.additionalEmployees.add(employee); + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/lazycollection/model/Employee.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/lazycollection/model/Employee.java new file mode 100644 index 0000000000..831518a365 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/lazycollection/model/Employee.java @@ -0,0 +1,88 @@ +package com.baeldung.hibernate.lazycollection.model; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OrderColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Entity; + +@Entity +public class Employee { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String address; + + public Employee() { + + } + + public Employee(String name, Branch mainBranch, Branch subBranch, Branch additionalBranch) { + this.name = name; + this.mainBranch = mainBranch; + this.subBranch = subBranch; + this.additionalBranch = additionalBranch; + } + + @ManyToOne + private Branch mainBranch; + + @ManyToOne + private Branch subBranch; + + @ManyToOne + private Branch additionalBranch; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Branch getMainBranch() { + return mainBranch; + } + + public void setMainBranch(Branch mainBranch) { + this.mainBranch = mainBranch; + } + + public Branch getSubBranch() { + return subBranch; + } + + public void setSubBranch(Branch subBranch) { + this.subBranch = subBranch; + } + + public Branch getAdditionalBranch() { + return additionalBranch; + } + + public void setAdditionalBranch(Branch additionalBranch) { + this.additionalBranch = additionalBranch; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/lazycollection/LazyCollectionIntegrationTest.java b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/lazycollection/LazyCollectionIntegrationTest.java new file mode 100644 index 0000000000..97888471a4 --- /dev/null +++ b/persistence-modules/hibernate-annotations/src/test/java/com/baeldung/hibernate/lazycollection/LazyCollectionIntegrationTest.java @@ -0,0 +1,104 @@ +package com.baeldung.hibernate.lazycollection; + +import com.baeldung.hibernate.lazycollection.model.Branch; +import com.baeldung.hibernate.lazycollection.model.Employee; +import org.hibernate.Hibernate; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.service.ServiceRegistry; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.annotation.PostConstruct; + +public class LazyCollectionIntegrationTest { + + private static SessionFactory sessionFactory; + + private Session session; + + Branch branch; + + @BeforeClass + public static void beforeTests() { + Configuration configuration = new Configuration().addAnnotatedClass(Branch.class) + .addAnnotatedClass(Employee.class).setProperty("hibernate.dialect", H2Dialect.class.getName()) + .setProperty("hibernate.connection.driver_class", org.h2.Driver.class.getName()) + .setProperty("hibernate.connection.url", "jdbc:h2:mem:test") + .setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "") + .setProperty("hibernate.hbm2ddl.auto", "update"); + + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() + .applySettings(configuration.getProperties()).build(); + + sessionFactory = configuration.buildSessionFactory(serviceRegistry); + + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + + branch = new Branch("Main Branch"); + + session.save(branch); + + Employee mainEmployee1 = new Employee("main employee 1", branch, null, null); + Employee mainEmployee2 = new Employee("main employee 2", branch, null, null); + Employee mainEmployee3 = new Employee("main employee 3", branch, null, null); + + session.save(mainEmployee1); + session.save(mainEmployee2); + session.save(mainEmployee3); + + Employee subEmployee1 = new Employee("sub employee 1", null, branch, null); + Employee subEmployee2 = new Employee("sub employee 2", null, branch, null); + Employee subEmployee3 = new Employee("sub employee 3", null, branch, null); + + session.save(subEmployee1); + session.save(subEmployee2); + session.save(subEmployee3); + + Employee additionalEmployee1 = new Employee("additional employee 1", null, null, branch); + Employee additionalEmployee2 = new Employee("additional employee 2", null, null, branch); + Employee additionalEmployee3 = new Employee("additional employee 3", null, null, branch); + + session.save(additionalEmployee1); + session.save(additionalEmployee2); + session.save(additionalEmployee3); + + session.flush(); + session.refresh(branch); + session.getTransaction().commit(); + session.close(); + } + + @Test + public void testLazyFetching() { + Assert.assertFalse(Hibernate.isInitialized(branch.getMainEmployees())); + } + + @Test + public void testEagerFetching() { + Assert.assertTrue(Hibernate.isInitialized(branch.getSubEmployees())); + } + + @Test + public void testExtraFetching() { + Assert.assertFalse(Hibernate.isInitialized(branch.getAdditionalEmployees())); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } +} diff --git a/persistence-modules/jnosql/jnosql-diana/pom.xml b/persistence-modules/jnosql/jnosql-diana/pom.xml index 79c455646c..d5746eef05 100644 --- a/persistence-modules/jnosql/jnosql-diana/pom.xml +++ b/persistence-modules/jnosql/jnosql-diana/pom.xml @@ -55,7 +55,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} document diff --git a/persistence-modules/jooq/pom.xml b/persistence-modules/jooq/pom.xml index cdda860040..2dababb02d 100644 --- a/persistence-modules/jooq/pom.xml +++ b/persistence-modules/jooq/pom.xml @@ -5,7 +5,7 @@ 4.0.0 jooq 0.0.1-SNAPSHOT - jooq-examples + jooq jar jOOQ Examples diff --git a/persistence-modules/spring-data-cosmosdb/pom.xml b/persistence-modules/spring-data-cosmosdb/pom.xml index f3c913195f..2eb6a6b038 100644 --- a/persistence-modules/spring-data-cosmosdb/pom.xml +++ b/persistence-modules/spring-data-cosmosdb/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-data-cosmosdb - spring-data-cosmos-db + spring-data-cosmosdb tutorial for spring-data-cosmosdb com.baeldung diff --git a/persistence-modules/spring-data-jpa-filtering/src/main/resources/logback.xml b/persistence-modules/spring-data-jpa-filtering/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-filtering/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java b/persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java index 96eaf4ed07..5fdcf6a787 100644 --- a/persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-filtering/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java @@ -6,18 +6,15 @@ import com.baeldung.projection.repository.PersonRepository; import com.baeldung.projection.view.AddressView; import com.baeldung.projection.view.PersonDto; import com.baeldung.projection.view.PersonView; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.jdbc.Sql; -import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD; @DataJpaTest -@RunWith(SpringRunner.class) @Sql(scripts = "/projection-insert-data.sql") @Sql(scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD) public class JpaProjectionIntegrationTest { diff --git a/pom.xml b/pom.xml index 13f24d7aea..ab3c73ff8a 100644 --- a/pom.xml +++ b/pom.xml @@ -1375,13 +1375,12 @@ 2.21.0 3.8.1 - 1.6.0 + 3.0.0 1.8 1.2.17 2.2.2.0 1.28 1.28 - 1.6.0 2.21.0 2.8.0 2.6 diff --git a/saas/pom.xml b/saas/pom.xml index be5d18f020..93965b37c4 100644 --- a/saas/pom.xml +++ b/saas/pom.xml @@ -40,7 +40,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} java com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed diff --git a/slack/pom.xml b/slack/pom.xml index ebe5ce2f60..51a4cf029f 100644 --- a/slack/pom.xml +++ b/slack/pom.xml @@ -45,7 +45,6 @@ org.codehaus.mojo exec-maven-plugin - 1.6.0 com.baeldung.examples.slack.MainClass diff --git a/spring-5-reactive-2/README.md b/spring-5-reactive-2/README.md index 397f6be57c..98a5f26433 100644 --- a/spring-5-reactive-2/README.md +++ b/spring-5-reactive-2/README.md @@ -9,4 +9,5 @@ This module contains articles about reactive Spring 5 - [Debugging Reactive Streams in Java](https://www.baeldung.com/spring-debugging-reactive-streams) - [Static Content in Spring WebFlux](https://www.baeldung.com/spring-webflux-static-content) - [Server-Sent Events in Spring](https://www.baeldung.com/spring-server-sent-events) +- [Backpressure Mechanism in Spring WebFlux](https://www.baeldung.com/spring-webflux-backpressure) - More articles: [[<-- prev]](/spring-5-reactive) diff --git a/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java b/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java new file mode 100644 index 0000000000..e7cb60dbf9 --- /dev/null +++ b/spring-5-reactive-2/src/test/java/com/baeldung/backpressure/BackpressureUnitTest.java @@ -0,0 +1,82 @@ +package com.baeldung.backpressure; + +import org.junit.jupiter.api.Test; +import reactor.core.publisher.BaseSubscriber; +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +public class BackpressureUnitTest { + + @Test + public void whenLimitRateSet_thenSplitIntoChunks() throws InterruptedException { + Flux limit = Flux.range(1, 25); + + limit.limitRate(10); + limit.subscribe( + value -> System.out.println(value), + err -> err.printStackTrace(), + () -> System.out.println("Finished!!"), + subscription -> subscription.request(15) + ); + + StepVerifier.create(limit) + .expectSubscription() + .thenRequest(15) + .expectNext(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .expectNext(11, 12, 13, 14, 15) + .thenRequest(10) + .expectNext(16, 17, 18, 19, 20, 21, 22, 23, 24, 25) + .verifyComplete(); + } + + @Test + public void whenRequestingChunks10_thenMessagesAreReceived() { + Flux request = Flux.range(1, 50); + + request.subscribe( + System.out::println, + err -> err.printStackTrace(), + () -> System.out.println("All 50 items have been successfully processed!!!"), + subscription -> { + for (int i = 0; i < 5; i++) { + System.out.println("Requesting the next 10 elements!!!"); + subscription.request(10); + } + } + ); + + StepVerifier.create(request) + .expectSubscription() + .thenRequest(10) + .expectNext(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .thenRequest(10) + .expectNext(11, 12, 13, 14, 15, 16, 17, 18, 19, 20) + .thenRequest(10) + .expectNext(21, 22, 23, 24, 25, 26, 27 , 28, 29 ,30) + .thenRequest(10) + .expectNext(31, 32, 33, 34, 35, 36, 37 , 38, 39 ,40) + .thenRequest(10) + .expectNext(41, 42, 43, 44, 45, 46, 47 , 48, 49 ,50) + .verifyComplete(); + } + + @Test + public void whenCancel_thenSubscriptionFinished() { + Flux cancel = Flux.range(1, 10).log(); + + cancel.subscribe(new BaseSubscriber() { + @Override + protected void hookOnNext(Integer value) { + request(3); + System.out.println(value); + cancel(); + } + }); + + StepVerifier.create(cancel) + .expectNext(1, 2, 3) + .thenCancel() + .verify(); + } +} + diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/timeout/WebClientTimeoutProvider.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/timeout/WebClientTimeoutProvider.java new file mode 100644 index 0000000000..6bb5a2db38 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/timeout/WebClientTimeoutProvider.java @@ -0,0 +1,89 @@ +package com.baeldung.webclient.timeout; + +import io.netty.channel.ChannelOption; +import io.netty.channel.epoll.EpollChannelOption; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; +import lombok.experimental.UtilityClass; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; +import reactor.netty.tcp.SslProvider; +import reactor.netty.transport.ProxyProvider; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +@UtilityClass +public class WebClientTimeoutProvider { + + public static WebClient defaultWebClient() { + HttpClient httpClient = HttpClient.create(); + + return buildWebClient(httpClient); + } + + public WebClient responseTimeoutClient() { + HttpClient httpClient = HttpClient.create() + .responseTimeout(Duration.ofSeconds(1)); + + return buildWebClient(httpClient); + } + + public WebClient connectionTimeoutClient() { + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000); + + return buildWebClient(httpClient); + } + + public WebClient connectionTimeoutWithKeepAliveClient() { + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(EpollChannelOption.TCP_KEEPIDLE, 300) + .option(EpollChannelOption.TCP_KEEPINTVL, 60) + .option(EpollChannelOption.TCP_KEEPCNT, 8); + + return buildWebClient(httpClient); + } + + public WebClient readWriteTimeoutClient() { + HttpClient httpClient = HttpClient.create() + .doOnConnected(conn -> conn + .addHandler(new ReadTimeoutHandler(5, TimeUnit.SECONDS)) + .addHandler(new WriteTimeoutHandler(5))); + + return buildWebClient(httpClient); + } + + public WebClient sslTimeoutClient() { + HttpClient httpClient = HttpClient.create() + .secure(spec -> spec + .sslContext(SslContextBuilder.forClient()) + .defaultConfiguration(SslProvider.DefaultConfigurationType.TCP) + .handshakeTimeout(Duration.ofSeconds(30)) + .closeNotifyFlushTimeout(Duration.ofSeconds(10)) + .closeNotifyReadTimeout(Duration.ofSeconds(10))); + + return buildWebClient(httpClient); + } + + public WebClient proxyTimeoutClient() { + HttpClient httpClient = HttpClient.create() + .proxy(spec -> spec + .type(ProxyProvider.Proxy.HTTP) + .host("http://proxy") + .port(8080) + .connectTimeoutMillis(3000)); + + return buildWebClient(httpClient); + } + + private WebClient buildWebClient(HttpClient httpClient) { + return WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build(); + } +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/timeout/WebClientTimeoutIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/timeout/WebClientTimeoutIntegrationTest.java new file mode 100644 index 0000000000..d2e009fe6a --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/timeout/WebClientTimeoutIntegrationTest.java @@ -0,0 +1,129 @@ +package com.baeldung.webclient.timeout; + +import com.github.tomakehurst.wiremock.WireMockServer; +import io.netty.handler.timeout.ReadTimeoutException; +import lombok.val; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientRequestException; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClientRequest; + + +import java.time.Duration; +import java.util.concurrent.TimeoutException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class WebClientTimeoutIntegrationTest { + + private WireMockServer wireMockServer; + + @Before + public void setup() { + wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); + wireMockServer.start(); + configureFor("localhost", wireMockServer.port()); + } + + @After + public void tearDown() { + wireMockServer.stop(); + } + + @AfterEach + public void tearDownEach() { + wireMockServer.resetAll(); + } + + @Test + public void givenResponseTimeoutClientWhenRequestTimeoutThenReadTimeoutException() { + val path = "/response-timeout"; + val delay = Math.toIntExact(Duration.ofSeconds(2).toMillis()); + stubFor(get(urlEqualTo(path)).willReturn(aResponse().withFixedDelay(delay) + .withStatus(HttpStatus.OK.value()))); + + val webClient = WebClientTimeoutProvider.responseTimeoutClient(); + + val ex = assertThrows(RuntimeException.class, () -> + webClient.get() + .uri(wireMockServer.baseUrl() + path) + .exchangeToMono(Mono::just) + .log() + .block()); + assertThat(ex).isInstanceOf(WebClientRequestException.class) + .getCause().isInstanceOf(ReadTimeoutException.class); + } + + @Test + public void givenReadWriteTimeoutClientWhenRequestTimeoutThenReadTimeoutException() { + val path = "/read-write-timeout"; + val delay = Math.toIntExact(Duration.ofSeconds(6).toMillis()); + stubFor(get(urlEqualTo(path)).willReturn(aResponse().withFixedDelay(delay) + .withStatus(HttpStatus.OK.value()))); + + val webClient = WebClientTimeoutProvider.readWriteTimeoutClient(); + + val ex = assertThrows(RuntimeException.class, () -> + webClient.get() + .uri(wireMockServer.baseUrl() + path) + .exchangeToMono(Mono::just) + .log() + .block()); + assertThat(ex).isInstanceOf(WebClientRequestException.class) + .getCause().isInstanceOf(ReadTimeoutException.class); + } + + @Test + public void givenNoTimeoutClientAndReactorTimeoutWhenRequestTimeoutThenTimeoutException() { + val path = "/reactor-timeout"; + val delay = Math.toIntExact(Duration.ofSeconds(5).toMillis()); + stubFor(get(urlEqualTo(path)).willReturn(aResponse().withFixedDelay(delay) + .withStatus(HttpStatus.OK.value()))); + + val webClient = WebClientTimeoutProvider.defaultWebClient(); + + val ex = assertThrows(RuntimeException.class, () -> + webClient.get() + .uri(wireMockServer.baseUrl() + path) + .exchangeToMono(Mono::just) + .timeout(Duration.ofSeconds(1)) + .log() + .block()); + assertThat(ex).hasMessageContaining("Did not observe any item") + .getCause().isInstanceOf(TimeoutException.class); + } + + @Test + public void givenNoTimeoutClientAndTimeoutHttpRequestWhenRequestTimeoutThenReadTimeoutException() { + val path = "/reactor-http-request-timeout"; + val delay = Math.toIntExact(Duration.ofSeconds(5).toMillis()); + stubFor(get(urlEqualTo(path)).willReturn(aResponse().withFixedDelay(delay) + .withStatus(HttpStatus.OK.value()))); + + val webClient = WebClientTimeoutProvider.defaultWebClient(); + + val ex = assertThrows(RuntimeException.class, () -> + webClient.get() + .uri(wireMockServer.baseUrl() + path) + .httpRequest(httpRequest -> { + HttpClientRequest reactorRequest = httpRequest.getNativeRequest(); + reactorRequest.responseTimeout(Duration.ofSeconds(1)); + }) + .exchangeToMono(Mono::just) + .log() + .block()); + assertThat(ex).isInstanceOf(WebClientRequestException.class) + .getCause().isInstanceOf(ReadTimeoutException.class); + } +} diff --git a/spring-5/src/test/java/com/baeldung/README.md b/spring-5/src/test/java/com/baeldung/README.md deleted file mode 100644 index 0ff61914d5..0000000000 --- a/spring-5/src/test/java/com/baeldung/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Concurrent Test Execution in Spring 5](https://www.baeldung.com/spring-5-concurrent-tests) diff --git a/spring-aop/pom.xml b/spring-aop/pom.xml index 74b6f48b46..09949a95f5 100644 --- a/spring-aop/pom.xml +++ b/spring-aop/pom.xml @@ -14,6 +14,15 @@ + + org.aspectj + aspectjrt + + + org.aspectj + aspectjweaver + + org.springframework.boot spring-boot-starter-aop @@ -23,7 +32,41 @@ spring-boot-starter-test test + + org.mockito + mockito-core + test + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj-plugin.version} + + ${java.version} + ${java.version} + ${java.version} + true + true + ignore + UTF-8 + + + + + compile + + + + + + + + + 1.11 + diff --git a/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/MyTracedService.java b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/MyTracedService.java new file mode 100644 index 0000000000..7c6934e67e --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/MyTracedService.java @@ -0,0 +1,19 @@ +package com.baeldung.aspectj.classmethodadvice; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.stereotype.Component; + +@Trace +@Component +public class MyTracedService { + private static final Log LOG = LogFactory.getLog(MyTracedService.class); + + public void performSomeLogic() { + LOG.info("Inside performSomeLogic..."); + } + + public void performSomeAdditionalLogic() { + LOG.info("Inside performSomeAdditionalLogic..."); + } +} diff --git a/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceConsumer.java b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceConsumer.java new file mode 100644 index 0000000000..1d5a017230 --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceConsumer.java @@ -0,0 +1,12 @@ +package com.baeldung.aspectj.classmethodadvice; + +import org.springframework.stereotype.Component; + +@Component +public class MyTracedServiceConsumer { + + public MyTracedServiceConsumer(MyTracedService myTracedService) { + myTracedService.performSomeLogic(); + myTracedService.performSomeAdditionalLogic(); + } +} diff --git a/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/Trace.java b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/Trace.java new file mode 100644 index 0000000000..0ab1547eeb --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/Trace.java @@ -0,0 +1,12 @@ +package com.baeldung.aspectj.classmethodadvice; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Trace { + +} diff --git a/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/TracingAspect.aj b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/TracingAspect.aj new file mode 100644 index 0000000000..20a42940b8 --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/aspectj/classmethodadvice/TracingAspect.aj @@ -0,0 +1,24 @@ +package com.baeldung.aspectj.classmethodadvice; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public aspect TracingAspect { + private static final Log LOG = LogFactory.getLog(TracingAspect.class); + + pointcut traceAnnotatedClasses(): within(@Trace *) && execution(* *(..)); + + Object around() : traceAnnotatedClasses() { + String signature = thisJoinPoint.getSignature().toShortString(); + LOG.trace("Entering " + signature); + try { + return proceed(); + } finally { + LOG.trace("Exiting " + signature); + } + } + + after() throwing (Exception e) : traceAnnotatedClasses() { + LOG.trace("Exception thrown from " + thisJoinPoint.getSignature().toShortString(), e); + } +} diff --git a/spring-aop/src/main/resources/logback.xml b/spring-aop/src/main/resources/logback.xml index 4eaa556705..84885fae62 100644 --- a/spring-aop/src/main/resources/logback.xml +++ b/spring-aop/src/main/resources/logback.xml @@ -17,6 +17,8 @@ + + diff --git a/spring-aop/src/test/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceConsumerUnitTest.java b/spring-aop/src/test/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceConsumerUnitTest.java new file mode 100644 index 0000000000..605ffc62c6 --- /dev/null +++ b/spring-aop/src/test/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceConsumerUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.aspectj.classmethodadvice; + +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.verify; + +public class MyTracedServiceConsumerUnitTest { + + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Spy + private MyTracedService myTracedService; + + @Test + public void whenCallingConsumer_thenServiceIsCalled() { + doNothing().when(myTracedService) + .performSomeLogic(); + doNothing().when(myTracedService) + .performSomeAdditionalLogic(); + + new MyTracedServiceConsumer(myTracedService); + + verify(myTracedService).performSomeLogic(); + verify(myTracedService).performSomeAdditionalLogic(); + } +} \ No newline at end of file diff --git a/spring-aop/src/test/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceUnitTest.java b/spring-aop/src/test/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceUnitTest.java new file mode 100644 index 0000000000..a5c3280d9e --- /dev/null +++ b/spring-aop/src/test/java/com/baeldung/aspectj/classmethodadvice/MyTracedServiceUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.aspectj.classmethodadvice; + +import org.junit.Rule; +import org.junit.Test; +import org.springframework.boot.test.system.OutputCaptureRule; + +import static org.junit.Assert.assertTrue; + +/* + * When running this test class, the tests may fail unless you build the code with Maven first. You + * must ensure the AspectJ compiler executes to weave in the Aspect's logic. Without the Aspect + * weaved into the class under test, the trace logging will not be written to stdout. + */ +public class MyTracedServiceUnitTest { + + @Rule + public OutputCaptureRule outputCaptureRule = new OutputCaptureRule(); + + @Test + public void whenPerformingSomeLogic_thenTraceAndInfoOutputIsWritten() { + MyTracedService myTracedService = new MyTracedService(); + myTracedService.performSomeLogic(); + + String output = outputCaptureRule.getOut(); + assertTrue(output.contains("TracingAspect - Entering MyTracedService.performSomeLogic")); + assertTrue(output.contains("MyTracedService - Inside performSomeLogic")); + assertTrue(output.contains("TracingAspect - Exiting MyTracedService.performSomeLogic")); + } + + @Test + public void whenPerformingSomeAdditionalLogic_thenTraceAndInfoOutputIsWritten() { + MyTracedService myTracedService = new MyTracedService(); + myTracedService.performSomeAdditionalLogic(); + + String output = outputCaptureRule.getOut(); + assertTrue(output.contains("TracingAspect - Entering MyTracedService.performSomeAdditionalLogic")); + assertTrue(output.contains("MyTracedService - Inside performSomeAdditionalLogic")); + assertTrue(output.contains("TracingAspect - Exiting MyTracedService.performSomeAdditionalLogic")); + } +} \ No newline at end of file diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 0288b03928..38100a333d 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -34,6 +34,7 @@ spring-boot-ctx-fluent spring-boot-deployment spring-boot-di + spring-boot-disable-logging spring-boot-camel spring-boot-ci-cd diff --git a/spring-boot-modules/spring-boot-actuator/README.md b/spring-boot-modules/spring-boot-actuator/README.md index 3e8ef3411b..9e2f30786f 100644 --- a/spring-boot-modules/spring-boot-actuator/README.md +++ b/spring-boot-modules/spring-boot-actuator/README.md @@ -10,3 +10,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Liveness and Readiness Probes in Spring Boot](https://www.baeldung.com/spring-liveness-readiness-probes) - [Custom Information in Spring Boot Info Endpoint](https://www.baeldung.com/spring-boot-info-actuator-custom) - [Health Indicators in Spring Boot](https://www.baeldung.com/spring-boot-health-indicators) +- [How to Enable All Endpoints in Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuator-enable-endpoints) diff --git a/spring-boot-modules/spring-boot-disable-logging/README.md b/spring-boot-modules/spring-boot-disable-logging/README.md new file mode 100644 index 0000000000..348c0f6dba --- /dev/null +++ b/spring-boot-modules/spring-boot-disable-logging/README.md @@ -0,0 +1,8 @@ +## Spring Boot Disable Logging + +This module contains articles about disabling logging in Spring Boot + + +### Relevant Articles: + +- [How to Disable Console Logging in Spring Boot](https://www.baeldung.com/spring-boot-disable-console-logging) diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/.gitignore b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/.gitignore similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-jul/.gitignore rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/.gitignore diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/pom.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml similarity index 96% rename from spring-boot-modules/spring-boot-runtime/disabling-console-jul/pom.xml rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml index 77629ffdd1..798332e809 100644 --- a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/pom.xml @@ -8,7 +8,7 @@ com.baeldung.spring-boot-modules - spring-boot-runtime + spring-boot-disable-logging 1.0.0-SNAPSHOT ../ diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/DisablingConsoleJulApp.java b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/DisablingConsoleJulApp.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/DisablingConsoleJulApp.java rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/DisablingConsoleJulApp.java diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/controllers/DisabledConsoleRestController.java b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/controllers/DisabledConsoleRestController.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/controllers/DisabledConsoleRestController.java rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/java/com/baeldung/springbootlogging/disablingconsole/jul/properties/controllers/DisabledConsoleRestController.java diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/resources/application.properties b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/resources/logging.properties b/spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/resources/logging.properties similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-jul/src/main/resources/logging.properties rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-jul/src/main/resources/logging.properties diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/.gitignore b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/.gitignore similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/.gitignore rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/.gitignore diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/pom.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml similarity index 95% rename from spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/pom.xml rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml index fd57eccbbf..f3f7fdf473 100644 --- a/spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/pom.xml @@ -8,7 +8,7 @@ com.baeldung.spring-boot-modules - spring-boot-runtime + spring-boot-disable-logging 1.0.0-SNAPSHOT ../ diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/DisablingConsoleLog4j2App.java b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/DisablingConsoleLog4j2App.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/DisablingConsoleLog4j2App.java rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/DisablingConsoleLog4j2App.java diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/controllers/DisabledConsoleRestController.java b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/controllers/DisabledConsoleRestController.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/controllers/DisabledConsoleRestController.java rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/src/main/java/com/baeldung/springbootlogging/disablingconsole/log4j2/xml/controllers/DisabledConsoleRestController.java diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/src/main/resources/log4j2.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/src/main/resources/log4j2.xml similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-log4j2/src/main/resources/log4j2.xml rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-log4j2/src/main/resources/log4j2.xml diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/.gitignore b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/.gitignore similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-logback/.gitignore rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/.gitignore diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/pom.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml similarity index 91% rename from spring-boot-modules/spring-boot-runtime/disabling-console-logback/pom.xml rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml index 8cb0e24bb7..741eae4ba4 100644 --- a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/pom.xml +++ b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/pom.xml @@ -8,7 +8,7 @@ com.baeldung.spring-boot-modules - spring-boot-runtime + spring-boot-disable-logging 1.0.0-SNAPSHOT ../ diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/DisablingConsoleLogbackApp.java b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/DisablingConsoleLogbackApp.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/DisablingConsoleLogbackApp.java rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/DisablingConsoleLogbackApp.java diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/controllers/DisabledConsoleRestController.java b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/controllers/DisabledConsoleRestController.java similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/controllers/DisabledConsoleRestController.java rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/java/com/baeldung/springbootlogging/disablingconsole/logback/xml/controllers/DisabledConsoleRestController.java diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/resources/application.properties b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/resources/application.properties similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/resources/logback-spring.xml b/spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/resources/logback-spring.xml similarity index 100% rename from spring-boot-modules/spring-boot-runtime/disabling-console-logback/src/main/resources/logback-spring.xml rename to spring-boot-modules/spring-boot-disable-logging/disabling-console-logback/src/main/resources/logback-spring.xml diff --git a/spring-boot-modules/spring-boot-disable-logging/pom.xml b/spring-boot-modules/spring-boot-disable-logging/pom.xml new file mode 100644 index 0000000000..020592ee29 --- /dev/null +++ b/spring-boot-modules/spring-boot-disable-logging/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + + spring-boot-disable-logging + 1.0.0-SNAPSHOT + pom + + spring-boot-disable-logging + + + disabling-console-jul + disabling-console-log4j2 + disabling-console-logback + + diff --git a/spring-boot-modules/spring-boot-property-exp/property-exp-custom-config/pom.xml b/spring-boot-modules/spring-boot-property-exp/property-exp-custom-config/pom.xml index f0df50cf76..07aeca9ad2 100644 --- a/spring-boot-modules/spring-boot-property-exp/property-exp-custom-config/pom.xml +++ b/spring-boot-modules/spring-boot-property-exp/property-exp-custom-config/pom.xml @@ -69,7 +69,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} com.baeldung.propertyexpansion.SpringBootPropertyExpansionApp @@ -80,7 +79,6 @@ Custom Property Value 2.7 - 1.6.0 diff --git a/spring-boot-modules/spring-boot-runtime/README.md b/spring-boot-modules/spring-boot-runtime/README.md index 271093421c..a36a17fa8e 100644 --- a/spring-boot-modules/spring-boot-runtime/README.md +++ b/spring-boot-modules/spring-boot-runtime/README.md @@ -6,7 +6,6 @@ This module contains articles about administering a Spring Boot runtime - [Shutdown a Spring Boot Application](https://www.baeldung.com/spring-boot-shutdown) - [Programmatically Restarting a Spring Boot Application](https://www.baeldung.com/java-restart-spring-boot-app) - [Logging HTTP Requests with Spring Boot Actuator HTTP Tracing](https://www.baeldung.com/spring-boot-actuator-http) - - [How to Disable Console Logging in Spring Boot](https://www.baeldung.com/spring-boot-disable-console-logging) - [Spring Boot Embedded Tomcat Logs](https://www.baeldung.com/spring-boot-embedded-tomcat-logs) - [Project Configuration with Spring](https://www.baeldung.com/project-configuration-with-spring) - [CORS with Spring](https://www.baeldung.com/spring-cors) diff --git a/spring-boot-modules/spring-boot-runtime/pom.xml b/spring-boot-modules/spring-boot-runtime/pom.xml index ce6fa7ea93..54bae61520 100644 --- a/spring-boot-modules/spring-boot-runtime/pom.xml +++ b/spring-boot-modules/spring-boot-runtime/pom.xml @@ -11,19 +11,12 @@ spring-boot-runtime - pom + jar spring-boot-runtime - Demo project for Spring Boot - - - disabling-console-jul - disabling-console-log4j2 - disabling-console-logback - + Demo project for Spring Boot Runtime - org.springframework.boot spring-boot-starter-web @@ -40,18 +33,6 @@ provided - - org.springframework.boot - spring-boot-starter-test - test - - - - commons-io - commons-io - ${commons-io.version} - - org.springframework.boot spring-boot-starter-data-jpa @@ -71,11 +52,25 @@ org.springframework.boot spring-boot-starter-security + - de.codecentric - spring-boot-admin-starter-client - ${spring-boot-admin-starter-client.version} + org.springframework.cloud + spring-cloud-starter + ${springcloud.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + + commons-io + commons-io + ${commons-io.version} + + org.springframework.security spring-security-test @@ -106,12 +101,6 @@ test - - org.springframework.cloud - spring-cloud-context - ${springcloud.version} - - org.apache.httpcomponents httpclient @@ -120,63 +109,12 @@ - - ${project.artifactId} - - - src/main/resources - true - - **/conf.properties - - - - - - - - autoconfiguration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*LiveTest.java - **/*IntegrationTest.java - **/*IntTest.java - - - **/AutoconfigurationTest.java - - - - - - - json - - - - - - - - 2.2 18.0 3.1.7 - 2.0.2.RELEASE + 3.0.2 4.5.8 - 2.1.6 diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java index f51bb52990..0f19c6dc48 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java @@ -2,6 +2,8 @@ package com.baeldung.web.log.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java index fb0c1d1d48..fda8a845e9 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/TaxiFareMVCConfig.java @@ -14,6 +14,6 @@ public class TaxiFareMVCConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(taxiFareRequestInterceptor).addPathPatterns("/**/taxifare/**/"); + registry.addInterceptor(taxiFareRequestInterceptor).addPathPatterns("/taxifare/*/"); } } diff --git a/spring-cloud-bus/pom.xml b/spring-cloud-bus/pom.xml index 15eed8dcf0..82d0bccd0b 100644 --- a/spring-cloud-bus/pom.xml +++ b/spring-cloud-bus/pom.xml @@ -34,8 +34,7 @@ - Hoxton.SR4 - 2.3.3.RELEASE + 2020.0.0 diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index c0e452afaf..ac717e85da 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -44,6 +44,7 @@ spring-cloud-circuit-breaker spring-cloud-eureka-self-preservation + spring-cloud-sentinel @@ -77,7 +78,7 @@ - Hoxton.SR4 + 2020.0.1 2.2.3.RELEASE 2.2.3.RELEASE 1.4.7.RELEASE diff --git a/spring-cloud/spring-cloud-docker/README.md b/spring-cloud/spring-cloud-docker/README.md new file mode 100644 index 0000000000..018d4ab1eb --- /dev/null +++ b/spring-cloud/spring-cloud-docker/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Dockerizing a Spring Boot Application](https://www.baeldung.com/dockerizing-spring-boot-application) diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java index d5f8180f20..ea8dd48e57 100644 --- a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung.spring.cloud.hystrix.rest.consumer; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; -@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = RestConsumerFeignApplication.class) @WebAppConfiguration public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml index 44e5bf2501..e96dc478a4 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml @@ -11,7 +11,7 @@ com.baeldung.spring.cloud spring-cloud-hystrix 1.0.0-SNAPSHOT - .. + ../ diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java index d3260a4517..d64f181c4f 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/consumer/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung.spring.cloud.hystrix.rest.consumer; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; -@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = RestConsumerApplication.class) @WebAppConfiguration public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/producer/SpringContextTest.java b/spring-cloud/spring-cloud-hystrix/rest-producer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/producer/SpringContextTest.java index bd871fc1da..3a4185d125 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-producer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/producer/SpringContextTest.java +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/src/test/java/com/baeldung/spring/cloud/hystrix/rest/producer/SpringContextTest.java @@ -1,11 +1,8 @@ package com.baeldung.spring.cloud.hystrix.rest.producer; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml index 07de78a92e..8e543db326 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/pom.xml @@ -15,13 +15,6 @@ - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} - pom - import - org.springframework.cloud spring-cloud-kubernetes-dependencies @@ -57,6 +50,7 @@ org.springframework.cloud spring-cloud-starter-netflix-hystrix + 2.2.7.RELEASE org.springframework.cloud @@ -65,6 +59,7 @@ org.springframework.cloud spring-cloud-starter-netflix-ribbon + 2.2.7.RELEASE @@ -89,8 +84,7 @@ - Hoxton.SR1 - 1.0.0.RELEASE + 1.1.8.RELEASE diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/src/test/java/com/baeldung/SpringContextTest.java index 8539e2af45..e2596492ed 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/client-service/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,10 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.spring.cloud.kubernetes.client.Application; -@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/pom.xml index 5459b77682..5ab017043c 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/pom.xml @@ -14,13 +14,6 @@ - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} - pom - import - ch.qos.logback logback-classic @@ -70,7 +63,6 @@ - Finchley.SR2 1.2.3 diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextTest.java b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextTest.java index 6e7f99fb0d..c8748e3213 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextTest.java +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-guide/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung.spring.cloud.kubernetes.travelagency; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-backend/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-backend/src/test/java/com/baeldung/SpringContextTest.java index 837c24264c..004a82f38c 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-backend/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-backend/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,10 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.spring.cloud.kubernetes.backend.KubernetesBackendApplication; -@RunWith(SpringRunner.class) @SpringBootTest(classes = KubernetesBackendApplication.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/src/test/java/com/baeldung/SpringContextTest.java index 1bf977a606..c28bc1394a 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,10 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.spring.cloud.kubernetes.frontend.KubernetesFrontendApplication; -@RunWith(SpringRunner.class) @SpringBootTest(classes = KubernetesFrontendApplication.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/java/com/baeldung/SpringContextTest.java index 7c605567d8..2cf2e053cf 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/liveness-example/src/test/java/com/baeldung/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung; import com.baeldung.liveness.Application; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/java/com/baeldung/SpringContextTest.java index 59802d220a..136c7aad7f 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-selfhealing/readiness-example/src/test/java/com/baeldung/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung; import com.baeldung.readiness.Application; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-kubernetes/pom.xml b/spring-cloud/spring-cloud-kubernetes/pom.xml index 44c429d8f5..7e494b61d9 100644 --- a/spring-cloud/spring-cloud-kubernetes/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/pom.xml @@ -15,6 +15,18 @@ ../../parent-boot-2 + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + kubernetes-minikube/demo-frontend kubernetes-minikube/demo-backend @@ -25,6 +37,6 @@ - 2.3.3.RELEASE + 2020.0.1 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-client/pom.xml b/spring-cloud/spring-cloud-ribbon-client/pom.xml index 7bc7b51d51..2c9820d179 100644 --- a/spring-cloud/spring-cloud-ribbon-client/pom.xml +++ b/spring-cloud/spring-cloud-ribbon-client/pom.xml @@ -37,6 +37,7 @@ org.springframework.cloud spring-cloud-starter-netflix-ribbon + 2.2.7.RELEASE org.springframework.boot @@ -45,8 +46,7 @@ - Hoxton.SR4 - 2.3.3.RELEASE + 2020.0.1 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/SpringContextTest.java index 949718e627..c62eb648c9 100644 --- a/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-ribbon-client/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,10 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.spring.cloud.ribbon.client.ServerLocationApp; -@RunWith(SpringRunner.class) @SpringBootTest(classes = ServerLocationApp.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-security/auth-client/pom.xml b/spring-cloud/spring-cloud-security/auth-client/pom.xml index 2852638c1a..c7606719f9 100644 --- a/spring-cloud/spring-cloud-security/auth-client/pom.xml +++ b/spring-cloud/spring-cloud-security/auth-client/pom.xml @@ -13,30 +13,15 @@ 1.0.0-SNAPSHOT - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - org.springframework.boot spring-boot-starter-web - - org.springframework.cloud - spring-cloud-starter-oauth2 - org.springframework.cloud spring-cloud-starter-netflix-zuul + ${spring-cloud-starter-netflix-zuul.version} org.springframework.boot @@ -92,7 +77,7 @@ 2.2.0 - Greenwich.SR1 + 2.2.7.RELEASE 3.4.1 4.3.1 diff --git a/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java index 33e5530667..caf7c15f90 100644 --- a/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,8 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.CloudSite; - -@RunWith(SpringRunner.class) @SpringBootTest(classes = CloudSite.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java index 1c5198125e..de38ce82a8 100644 --- a/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java +++ b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java @@ -1,13 +1,10 @@ package com.baeldung.example.springoath2; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.CloudSite; -@RunWith(SpringRunner.class) @SpringBootTest(classes = CloudSite.class) public class Springoath2ApplicationIntegrationTest { diff --git a/spring-cloud/spring-cloud-security/auth-resource/pom.xml b/spring-cloud/spring-cloud-security/auth-resource/pom.xml index 0a642250e7..d3f9eaf795 100644 --- a/spring-cloud/spring-cloud-security/auth-resource/pom.xml +++ b/spring-cloud/spring-cloud-security/auth-resource/pom.xml @@ -13,18 +13,6 @@ 1.0.0-SNAPSHOT - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - org.springframework.boot @@ -56,7 +44,6 @@ - Greenwich.SR1 1.0.10.RELEASE diff --git a/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java index cce93f2c3e..bf96f65993 100644 --- a/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,8 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.Application; - -@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/service/personservice/PersonserviceApplicationIntegrationTest.java b/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/service/personservice/PersonserviceApplicationIntegrationTest.java index 3caa06ba4d..aa277e1419 100644 --- a/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/service/personservice/PersonserviceApplicationIntegrationTest.java +++ b/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/service/personservice/PersonserviceApplicationIntegrationTest.java @@ -1,11 +1,8 @@ package com.baeldung.service.personservice; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest public class PersonserviceApplicationIntegrationTest { diff --git a/spring-cloud/spring-cloud-security/auth-server/pom.xml b/spring-cloud/spring-cloud-security/auth-server/pom.xml index f6d0861552..59ddedf1b2 100644 --- a/spring-cloud/spring-cloud-security/auth-server/pom.xml +++ b/spring-cloud/spring-cloud-security/auth-server/pom.xml @@ -31,14 +31,9 @@ spring-boot-starter-thymeleaf - org.springframework.cloud - spring-cloud-starter-oauth2 - ${spring-cloud-starter-oauth2.version} + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure - - 2.1.2.RELEASE - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java index d61a9c279f..ddda8fd625 100644 --- a/spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java @@ -1,13 +1,8 @@ package com.baeldung; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.AuthServer; - -@RunWith(SpringRunner.class) @SpringBootTest(classes = AuthServer.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-security/pom.xml b/spring-cloud/spring-cloud-security/pom.xml index f861b892c0..53b95380ed 100644 --- a/spring-cloud/spring-cloud-security/pom.xml +++ b/spring-cloud/spring-cloud-security/pom.xml @@ -14,6 +14,18 @@ ../../parent-boot-2 + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + auth-client auth-resource @@ -21,6 +33,7 @@ - 2.3.3.RELEASE + 2020.0.1 + diff --git a/spring-cloud/spring-cloud-sentinel/README.md b/spring-cloud/spring-cloud-sentinel/README.md new file mode 100644 index 0000000000..6b12fea608 --- /dev/null +++ b/spring-cloud/spring-cloud-sentinel/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Introduction to Alibaba Sentinel](https://www.baeldung.com/java-sentinel-intro) diff --git a/spring-cloud/spring-cloud-sentinel/pom.xml b/spring-cloud/spring-cloud-sentinel/pom.xml new file mode 100644 index 0000000000..612cbcbfbe --- /dev/null +++ b/spring-cloud/spring-cloud-sentinel/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + spring-cloud-sentinel + spring-cloud-sentinel + http://maven.apache.org + pom + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + com.alibaba.csp + sentinel-core + 1.8.0 + + + com.alibaba.csp + sentinel-annotation-aspectj + 1.8.0 + + + com.alibaba.csp + sentinel-transport-simple-http + 1.8.0 + + + + + UTF-8 + + diff --git a/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/SentinelApplication.java b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/SentinelApplication.java new file mode 100644 index 0000000000..4d921844df --- /dev/null +++ b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/SentinelApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.cloud.sentinel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SentinelApplication { + public static void main(String[] args) { + SpringApplication.run(SentinelApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/config/SentinelAspectConfiguration.java b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/config/SentinelAspectConfiguration.java new file mode 100644 index 0000000000..4dfacef999 --- /dev/null +++ b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/config/SentinelAspectConfiguration.java @@ -0,0 +1,65 @@ +package com.baeldung.spring.cloud.sentinel.config; + +import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect; +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; +import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import com.alibaba.csp.sentinel.slots.system.SystemRule; +import com.alibaba.csp.sentinel.slots.system.SystemRuleManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; + +@Configuration +public class SentinelAspectConfiguration { + + public static final String RESOURCE_NAME = "greeting"; + + @Bean + public SentinelResourceAspect sentinelResourceAspect() { + return new SentinelResourceAspect(); + } + + @PostConstruct + public void init() { + initFlowRules(); + initDegradeRules(); + initSystemProtectionRules(); + } + + private void initFlowRules() { + List flowRules = new ArrayList<>(); + FlowRule flowRule = new FlowRule(); + // Defined resource + flowRule.setResource(RESOURCE_NAME); + flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); + // number of requests that QPS can pass in a second + flowRule.setCount(1); + flowRules.add(flowRule); + FlowRuleManager.loadRules(flowRules); + } + + private void initDegradeRules() { + List rules = new ArrayList(); + DegradeRule rule = new DegradeRule(); + rule.setResource(RESOURCE_NAME); + rule.setCount(10); + rule.setTimeWindow(10); + rules.add(rule); + DegradeRuleManager.loadRules(rules); + } + + private void initSystemProtectionRules() { + List rules = new ArrayList<>(); + SystemRule rule = new SystemRule(); + rule.setHighestSystemLoad(10); + rules.add(rule); + SystemRuleManager.loadRules(rules); + } + +} diff --git a/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/controller/GreetingController.java b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/controller/GreetingController.java new file mode 100644 index 0000000000..fa3852466d --- /dev/null +++ b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/controller/GreetingController.java @@ -0,0 +1,20 @@ +package com.baeldung.spring.cloud.sentinel.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.spring.cloud.sentinel.service.GreetingService; + +@RestController +public class GreetingController { + + @Autowired + private GreetingService greetingService; + + @GetMapping("/hello") + public String getGreeting() { + return greetingService.getGreeting(); + } + +} diff --git a/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/service/GreetingService.java b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/service/GreetingService.java new file mode 100644 index 0000000000..e60d679b92 --- /dev/null +++ b/spring-cloud/spring-cloud-sentinel/src/main/java/com/baeldung/spring/cloud/sentinel/service/GreetingService.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.cloud.sentinel.service; + +import com.alibaba.csp.sentinel.annotation.SentinelResource; +import org.springframework.stereotype.Service; + +@Service +public class GreetingService { + + @SentinelResource(value = "greeting", fallback = "getGreetingFallback") + public String getGreeting() { + return "Hello World!"; + } + + public String getGreetingFallback(Throwable e) { + e.printStackTrace(); + return "Bye world!"; + } + +} diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml index 871218e78c..24e783ff30 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml @@ -37,12 +37,10 @@ org.springframework spring-web - ${springframework.version} org.springframework.cloud spring-cloud-starter-zookeeper-discovery - ${spring-cloud-starter-zookeeper-discovery.version} commons-logging diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/src/test/java/com/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-zookeeper/Greeting/src/test/java/com/baeldung/SpringContextTest.java index f7325e425f..d08c772468 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/test/java/com/baeldung/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung; import com.baeldung.spring.cloud.greeting.GreetingApplication; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = GreetingApplication.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml b/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml index 3a263e4ded..777b857403 100644 --- a/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml @@ -33,12 +33,10 @@ org.springframework spring-web - ${springframework.version} org.springframework.cloud spring-cloud-starter-zookeeper-discovery - ${spring-cloud-starter-zookeeper-discovery.version} commons-logging diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextTest.java b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextTest.java index df7335dfa6..04b5b6c1a4 100644 --- a/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextTest.java +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextTest.java @@ -1,12 +1,9 @@ package com.baeldung.spring.cloud.helloworld; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = HelloWorldApplication.class) public class SpringContextTest { diff --git a/spring-cloud/spring-cloud-zookeeper/pom.xml b/spring-cloud/spring-cloud-zookeeper/pom.xml index e3241da02c..31bf043ac0 100644 --- a/spring-cloud/spring-cloud-zookeeper/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/pom.xml @@ -19,8 +19,6 @@ 5.2.7.RELEASE - 1.0.3.RELEASE - 2.3.3.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml b/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml index d2914b48bf..e66110fb23 100644 --- a/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml +++ b/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 weather-service - Weather Service + weather-service Weather Service for Zuul Fallback Test diff --git a/spring-core-2/src/main/resources/application.properties b/spring-core-2/src/main/resources/application.properties index cbfe3f2df2..d482330b83 100644 --- a/spring-core-2/src/main/resources/application.properties +++ b/spring-core-2/src/main/resources/application.properties @@ -1 +1,28 @@ -spring.profiles.active=@spring.profiles.active@ \ No newline at end of file +spring.profiles.active=@spring.profiles.active@ + +my.prop=used-always-in-all-profiles + +#--- +spring.config.activate.on-profile=dev +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://localhost:3306/db +spring.datasource.username=root +spring.datasource.password=root + +#--- +spring.config.activate.on-profile=production +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa + +#--- +spring.profiles.group.production=proddb,prodquartz + +#--- +spring.config.activate.on-profile=proddb +db=url_to_production_db + +#--- +spring.config.activate.on-profile=prodquartz +quartz=url_to_quartz_scheduler \ No newline at end of file diff --git a/spring-core-5/README.md b/spring-core-5/README.md index 6befae7372..4315535e69 100644 --- a/spring-core-5/README.md +++ b/spring-core-5/README.md @@ -6,4 +6,5 @@ This module contains articles about core Spring functionality - [Spring @Component Annotation](https://www.baeldung.com/spring-component-annotation) - [Solving Spring’s “not eligible for auto-proxying” Warning](https://www.baeldung.com/spring-not-eligible-for-auto-proxying) +- [Spring Bean Names](https://www.baeldung.com/spring-bean-names) - More articles: [[<-- prev]](/spring-core-4) diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Animal.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Animal.java new file mode 100644 index 0000000000..d29b4139c9 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Animal.java @@ -0,0 +1,5 @@ +package com.baeldung.springbean.naming.component; + +public interface Animal { + String name(); +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Cat.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Cat.java new file mode 100644 index 0000000000..8c70078822 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Cat.java @@ -0,0 +1,14 @@ +package com.baeldung.springbean.naming.component; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +@Qualifier("cat") +public class Cat implements Animal { + + @Override + public String name() { + return "Cat"; + } +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/CustomComponent.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/CustomComponent.java new file mode 100644 index 0000000000..71ebfea1a2 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/CustomComponent.java @@ -0,0 +1,7 @@ +package com.baeldung.springbean.naming.component; + +import org.springframework.stereotype.Component; + +@Component("myBean") +public class CustomComponent { +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Dog.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Dog.java new file mode 100644 index 0000000000..a6d6015ab3 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/component/Dog.java @@ -0,0 +1,13 @@ +package com.baeldung.springbean.naming.component; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +@Qualifier("dog") +public class Dog implements Animal { + @Override + public String name() { + return "Dog"; + } +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/configuration/AuditConfiguration.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/configuration/AuditConfiguration.java new file mode 100644 index 0000000000..a29dc6ada1 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/configuration/AuditConfiguration.java @@ -0,0 +1,14 @@ +package com.baeldung.springbean.naming.configuration; + +import com.baeldung.springbean.naming.service.AuditService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AuditConfiguration { + + @Bean + public AuditService audit() { + return new AuditService(); + } +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/configuration/MyConfiguration.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/configuration/MyConfiguration.java new file mode 100644 index 0000000000..f1a18bac95 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/configuration/MyConfiguration.java @@ -0,0 +1,19 @@ +package com.baeldung.springbean.naming.configuration; + +import com.baeldung.springbean.naming.component.CustomComponent; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration("configuration") +public class MyConfiguration { + + @Bean("qualifierComponent") + public CustomComponent component() { + return new CustomComponent(); + } + + @Bean("beanComponent") + public CustomComponent myComponent() { + return new CustomComponent(); + } +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/controller/MessagingController.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/controller/MessagingController.java new file mode 100644 index 0000000000..89d32aba80 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/controller/MessagingController.java @@ -0,0 +1,12 @@ +package com.baeldung.springbean.naming.controller; + +import com.baeldung.springbean.naming.service.MessagingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Controller +public class MessagingController { + + @Autowired + private MessagingService service; +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/AuditService.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/AuditService.java new file mode 100644 index 0000000000..07811c8104 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/AuditService.java @@ -0,0 +1,4 @@ +package com.baeldung.springbean.naming.service; + +public class AuditService { +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/LoggingService.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/LoggingService.java new file mode 100644 index 0000000000..3be4e9a028 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/LoggingService.java @@ -0,0 +1,7 @@ +package com.baeldung.springbean.naming.service; + +import org.springframework.stereotype.Service; + +@Service +public class LoggingService { +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/MessagingService.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/MessagingService.java new file mode 100644 index 0000000000..2494712dd3 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/MessagingService.java @@ -0,0 +1,4 @@ +package com.baeldung.springbean.naming.service; + +public interface MessagingService { +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/MessagingServiceImpl.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/MessagingServiceImpl.java new file mode 100644 index 0000000000..2b7cb84742 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/MessagingServiceImpl.java @@ -0,0 +1,14 @@ +package com.baeldung.springbean.naming.service; + +import com.baeldung.springbean.naming.component.CustomComponent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class MessagingServiceImpl implements MessagingService { + + @Autowired + @Qualifier("qualifierComponent") + private CustomComponent customComponent; +} diff --git a/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/PetShow.java b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/PetShow.java new file mode 100644 index 0000000000..dc74bef4d0 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/springbean/naming/service/PetShow.java @@ -0,0 +1,26 @@ +package com.baeldung.springbean.naming.service; + +import com.baeldung.springbean.naming.component.Animal; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class PetShow { + + @Autowired + @Qualifier("dog") + private Animal dog; + + @Autowired + @Qualifier("cat") + private Animal cat; + + public Animal getDog() { + return dog; + } + + public Animal getCat() { + return cat; + } +} diff --git a/spring-core-5/src/test/java/com/baeldung/component/autoproxying/EligibleForAutoProxyingIntegrationTest.java b/spring-core-5/src/test/java/com/baeldung/component/autoproxying/EligibleForAutoProxyingIntegrationTest.java index 4af700813a..c7943e355b 100644 --- a/spring-core-5/src/test/java/com/baeldung/component/autoproxying/EligibleForAutoProxyingIntegrationTest.java +++ b/spring-core-5/src/test/java/com/baeldung/component/autoproxying/EligibleForAutoProxyingIntegrationTest.java @@ -40,7 +40,7 @@ public class EligibleForAutoProxyingIntegrationTest { @Test public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShowAndGroupFieldPopulated() { - List notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] " + + List notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.component.autoproxying.RandomIntGenerator] " + "is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)"); assertEquals(0, notEligibleEvents.size()); diff --git a/spring-core-5/src/test/java/com/baeldung/component/autoproxying/NotEligibleForAutoProxyingIntegrationTest.java b/spring-core-5/src/test/java/com/baeldung/component/autoproxying/NotEligibleForAutoProxyingIntegrationTest.java index 9434f77a30..f49f1ce602 100644 --- a/spring-core-5/src/test/java/com/baeldung/component/autoproxying/NotEligibleForAutoProxyingIntegrationTest.java +++ b/spring-core-5/src/test/java/com/baeldung/component/autoproxying/NotEligibleForAutoProxyingIntegrationTest.java @@ -39,7 +39,7 @@ public class NotEligibleForAutoProxyingIntegrationTest { @Test public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShowAndGroupFieldNotPopulated() { - List notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] " + + List notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.component.autoproxying.RandomIntGenerator] " + "is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)"); assertEquals(1, notEligibleEvents.size()); diff --git a/spring-core-5/src/test/java/com/baeldung/springbean/naming/SpringBeanNamingUnitTest.java b/spring-core-5/src/test/java/com/baeldung/springbean/naming/SpringBeanNamingUnitTest.java new file mode 100644 index 0000000000..cccfe22e34 --- /dev/null +++ b/spring-core-5/src/test/java/com/baeldung/springbean/naming/SpringBeanNamingUnitTest.java @@ -0,0 +1,65 @@ +package com.baeldung.springbean.naming; + +import com.baeldung.springbean.naming.component.Cat; +import com.baeldung.springbean.naming.component.Dog; +import com.baeldung.springbean.naming.service.PetShow; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@ExtendWith(SpringExtension.class) +public class SpringBeanNamingUnitTest { + + private AnnotationConfigApplicationContext context; + + @BeforeEach + void setUp() { + context = new AnnotationConfigApplicationContext(); + context.scan("com.baeldung.springbean.naming"); + context.refresh(); + } + + // To name a bean spring gets the class name and converts the first letter to lowercase. + // Default naming strategy of the spring bean which is using class level annotation + + @Test + void givenLoggingServiceBeanIsCreated_whenThereIsNoValueProvided_thenBeanNameShouldBeDefaultName() { + assertNotNull(context.getBean("loggingService")); + } + + // In this case, to name a bean spring gets the class name and converts the first letter to lowercase. + @Test + void givenAuditServiceBeanIsCreatedWithMethodLevelAnnotation_whenThereIsNoValueProvided_thenBeanNameShouldBeTheNameOfMethod() { + assertNotNull(context.getBean("audit")); + } + + // spring will create the bean of type CustomComponent with the name "myBean". + // As we're explicitly giving the name to the bean, spring will use this name to refer to it. + @Test + void givenCustomComponentBeanIsCreate_whenThereIsCustomNameGivenToBean_thenBeanShouldBeIdentifiedByThatName() { + assertNotNull(context.getBean("myBean")); + } + + @Test + void givenCustomComponentBeanIsCreated_whenCustomNameIsGivenOnMethodLevelAnnotation_thenBeanShouldBeIdentifiedByThatName() { + assertNotNull(context.getBean("beanComponent")); + assertNotNull(context.getBean("configuration")); + assertNotNull(context.getBean("qualifierComponent")); + } + + @Test + void givenMultipleImplementationsOfAnimal_whenFieldIsInjectedWithQualifiedName_thenTheSpecificBeanShouldGetInjected() { + PetShow petShow = (PetShow) context.getBean("petShow"); + + assertNotNull(context.getBean("cat")); + assertNotNull(context.getBean("dog")); + + assertThat(petShow.getCat().getClass()).isEqualTo(Cat.class); + assertThat(petShow.getDog().getClass()).isEqualTo(Dog.class); + } +} diff --git a/spring-integration/pom.xml b/spring-integration/pom.xml index 11b2803095..f46445a39f 100644 --- a/spring-integration/pom.xml +++ b/spring-integration/pom.xml @@ -108,7 +108,6 @@ org.codehaus.mojo exec-maven-plugin - ${exec-maven-plugin.version} com.baeldung.samples.FileCopyConfig @@ -122,7 +121,6 @@ 1.4.7 1.1.1 2.10 - 1.5.0 1.4.197
diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml index 78e406dc84..bb2702fc9d 100644 --- a/spring-security-modules/pom.xml +++ b/spring-security-modules/pom.xml @@ -31,6 +31,7 @@ spring-security-web-angular/server spring-security-web-boot-1 spring-security-web-boot-2 + spring-security-web-boot-3 spring-security-web-digest-auth spring-security-web-login spring-security-web-mvc-custom diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/SpringSecurityConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/SpringSecurityConfig.java index 88814038a8..3d4182f423 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/SpringSecurityConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/SpringSecurityConfig.java @@ -28,12 +28,15 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private WebApplicationContext applicationContext; - private CustomUserDetailsService userDetailsService; + @Autowired private AuthenticationSuccessHandlerImpl successHandler; + @Autowired private DataSource dataSource; + private CustomUserDetailsService userDetailsService; + @PostConstruct public void completeSetup() { userDetailsService = applicationContext.getBean(CustomUserDetailsService.class); @@ -50,7 +53,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { } @Override - public void configure(WebSecurity web) throws Exception { + public void configure(WebSecurity web) { web.ignoring() .antMatchers("/resources/**"); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/AppUser.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/AppUser.java index 2efd24e879..34bf775c1c 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/AppUser.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/AppUser.java @@ -18,13 +18,17 @@ public class AppUser { private long id; private String name; + @Column(unique = true) private String username; + private String password; + private boolean enabled = true; + private Date lastLogin; - private AppUser() { + public AppUser() { } public AppUser(String name, String email, String password) { diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/Tweet.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/Tweet.java index d8496f89be..2f593d5784 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/Tweet.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/models/Tweet.java @@ -15,15 +15,27 @@ import javax.persistence.Table; @Entity @Table(name = "Tweet") public class Tweet { + @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; + private String tweet; + private String owner; + @ElementCollection(targetClass = String.class, fetch = FetchType.EAGER) @CollectionTable(name = "Tweet_Likes") private Set likes = new HashSet<>(); + public Tweet() { + } + + public Tweet(String tweet, String owner) { + this.tweet = tweet; + this.owner = owner; + } + public long getId() { return id; } @@ -32,14 +44,6 @@ public class Tweet { this.id = id; } - private Tweet() { - } - - public Tweet(String tweet, String owner) { - this.tweet = tweet; - this.owner = owner; - } - public String getTweet() { return tweet; } @@ -63,5 +67,4 @@ public class Tweet { public void setLikes(Set likes) { this.likes = likes; } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/TweetRepository.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/TweetRepository.java index 4e4b16a151..685a1a8ab9 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/TweetRepository.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/TweetRepository.java @@ -9,6 +9,6 @@ import com.baeldung.relationships.models.Tweet; public interface TweetRepository extends PagingAndSortingRepository { - @Query("select twt from Tweet twt JOIN twt.likes as lk where lk = ?#{ principal?.username } or twt.owner = ?#{ principal?.username }") + @Query("SELECT twt FROM Tweet twt JOIN twt.likes AS lk WHERE lk = ?#{ principal?.username } OR twt.owner = ?#{ principal?.username }") Page getMyTweetsAndTheOnesILiked(Pageable pageable); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/UserRepository.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/UserRepository.java index 883ea332f8..c93acecd78 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/UserRepository.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/repositories/UserRepository.java @@ -12,6 +12,7 @@ import org.springframework.transaction.annotation.Transactional; import com.baeldung.relationships.models.AppUser; public interface UserRepository extends CrudRepository { + AppUser findByUsername(String username); List findByName(String name); @@ -19,5 +20,5 @@ public interface UserRepository extends CrudRepository { @Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE u.username = ?#{ principal?.username }") @Modifying @Transactional - public void updateLastLogin(@Param("lastLogin") Date lastLogin); + void updateLastLogin(@Param("lastLogin") Date lastLogin); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AppUserPrincipal.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AppUserPrincipal.java index 1ae7d95e41..129e44fb0f 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AppUserPrincipal.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AppUserPrincipal.java @@ -2,7 +2,6 @@ package com.baeldung.relationships.security; import java.util.Collection; import java.util.Collections; -import java.util.List; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -14,14 +13,10 @@ public class AppUserPrincipal implements UserDetails { private final AppUser user; - // - public AppUserPrincipal(AppUser user) { this.user = user; } - // - @Override public String getUsername() { return user.getUsername(); @@ -34,8 +29,7 @@ public class AppUserPrincipal implements UserDetails { @Override public Collection getAuthorities() { - final List authorities = Collections.singletonList(new SimpleGrantedAuthority("User")); - return authorities; + return Collections.singletonList(new SimpleGrantedAuthority("User")); } @Override @@ -58,10 +52,7 @@ public class AppUserPrincipal implements UserDetails { return true; } - // - public AppUser getAppUser() { return user; } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AuthenticationSuccessHandlerImpl.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AuthenticationSuccessHandlerImpl.java index 1b85294467..3636a20c2d 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AuthenticationSuccessHandlerImpl.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/AuthenticationSuccessHandlerImpl.java @@ -1,9 +1,7 @@ package com.baeldung.relationships.security; -import java.io.IOException; import java.util.Date; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -21,7 +19,7 @@ public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHa private UserRepository userRepository; @Override - public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) throws IOException, ServletException { + public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) { userRepository.updateLastLogin(new Date()); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/CustomUserDetailsService.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/CustomUserDetailsService.java index 10c266bb74..f8a0f00d90 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/CustomUserDetailsService.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/security/CustomUserDetailsService.java @@ -17,11 +17,8 @@ public class CustomUserDetailsService implements UserDetailsService { @Autowired private WebApplicationContext applicationContext; - private UserRepository userRepository; - public CustomUserDetailsService() { - super(); - } + private UserRepository userRepository; @PostConstruct public void completeSetup() { @@ -36,5 +33,4 @@ public class CustomUserDetailsService implements UserDetailsService { } return new AppUserPrincipal(appUser); } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/util/DummyContentUtil.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/util/DummyContentUtil.java index b8e5192b48..5c71728c6f 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/util/DummyContentUtil.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/relationships/util/DummyContentUtil.java @@ -15,7 +15,7 @@ import com.baeldung.relationships.models.Tweet; public class DummyContentUtil { - public static final List generateDummyUsers() { + public static List generateDummyUsers() { List appUsers = new ArrayList<>(); BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); appUsers.add(new AppUser("Lionel Messi", "lionel@messi.com", passwordEncoder.encode("li1234"))); @@ -31,7 +31,7 @@ public class DummyContentUtil { return appUsers; } - public static final List generateDummyTweets(List users) { + public static List generateDummyTweets(List users) { List tweets = new ArrayList<>(); Random random = new Random(); IntStream.range(0, 9) @@ -59,5 +59,4 @@ public class DummyContentUtil { grantedAuthorities.add(grantedAuthority); return grantedAuthorities; } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/Application.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/Application.java index e7ace1f962..b4aa242ddc 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/Application.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/Application.java @@ -3,11 +3,9 @@ package com.baeldung.roles.custom; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.PropertySource; @SpringBootApplication -@ComponentScan("com.baeldung.roles.custom") @PropertySource("classpath:application-defaults.properties") public class Application extends SpringBootServletInitializer { public static void main(String[] args) { diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/config/MvcConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/config/MvcConfig.java index c99d1e38a5..9ecd5c3abd 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/config/MvcConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/config/MvcConfig.java @@ -13,11 +13,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { - public MvcConfig() { - super(); - } - - // @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/SetupData.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/SetupData.java index ab57e7436c..25bf51507a 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/SetupData.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/SetupData.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Component; @Component public class SetupData { + @Autowired private UserRepository userRepository; @@ -39,18 +40,18 @@ public class SetupData { private void initUsers() { final Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE"); final Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE"); - // + final User user1 = new User(); user1.setUsername("john"); user1.setPassword(encoder.encode("123")); - user1.setPrivileges(new HashSet(Arrays.asList(privilege1))); + user1.setPrivileges(new HashSet<>(Arrays.asList(privilege1))); user1.setOrganization(organizationRepository.findByName("FirstOrg")); userRepository.save(user1); - // + final User user2 = new User(); user2.setUsername("tom"); user2.setPassword(encoder.encode("111")); - user2.setPrivileges(new HashSet(Arrays.asList(privilege1, privilege2))); + user2.setPrivileges(new HashSet<>(Arrays.asList(privilege1, privilege2))); user2.setOrganization(organizationRepository.findByName("SecondOrg")); userRepository.save(user2); } @@ -58,7 +59,7 @@ public class SetupData { private void initOrganizations() { final Organization org1 = new Organization("FirstOrg"); organizationRepository.save(org1); - // + final Organization org2 = new Organization("SecondOrg"); organizationRepository.save(org2); } @@ -66,7 +67,7 @@ public class SetupData { private void initPrivileges() { final Privilege privilege1 = new Privilege("FOO_READ_PRIVILEGE"); privilegeRepository.save(privilege1); - // + final Privilege privilege2 = new Privilege("FOO_WRITE_PRIVILEGE"); privilegeRepository.save(privilege2); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/OrganizationRepository.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/OrganizationRepository.java index 2f585f3527..e5c99af331 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/OrganizationRepository.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/OrganizationRepository.java @@ -5,6 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface OrganizationRepository extends JpaRepository { - public Organization findByName(String name); - + Organization findByName(String name); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/PrivilegeRepository.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/PrivilegeRepository.java index c83e0f505e..43b8c317c5 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/PrivilegeRepository.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/PrivilegeRepository.java @@ -5,6 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface PrivilegeRepository extends JpaRepository { - public Privilege findByName(String name); - + Privilege findByName(String name); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/UserRepository.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/UserRepository.java index 884a998219..d6744f4d51 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/UserRepository.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/dao/UserRepository.java @@ -10,5 +10,4 @@ public interface UserRepository extends JpaRepository { @Transactional void removeUserByUsername(String username); - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Foo.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Foo.java index 3dbf48f7ce..eab7696b47 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Foo.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Foo.java @@ -8,6 +8,7 @@ import javax.persistence.Id; @Entity public class Foo { + @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @@ -15,19 +16,13 @@ public class Foo { @Column(nullable = false) private String name; - // - public Foo() { - super(); } public Foo(String name) { - super(); this.name = name; } - // - public Long getId() { return id; } @@ -44,8 +39,6 @@ public class Foo { this.name = name; } - // - @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Organization.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Organization.java index 0d0220b6b2..f9dc992b8c 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Organization.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Organization.java @@ -16,19 +16,13 @@ public class Organization { @Column(nullable = false, unique = true) private String name; - // - public Organization() { - super(); } public Organization(String name) { - super(); this.name = name; } - // - public Long getId() { return id; } @@ -45,8 +39,6 @@ public class Organization { this.name = name; } - // - @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Privilege.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Privilege.java index 60e0506641..7757ec1bf6 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Privilege.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/Privilege.java @@ -16,19 +16,13 @@ public class Privilege { @Column(nullable = false, unique = true) private String name; - // - public Privilege() { - super(); } public Privilege(String name) { - super(); this.name = name; } - // - public Long getId() { return id; } @@ -45,8 +39,6 @@ public class Privilege { this.name = name; } - // - @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/User.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/User.java index 219f40a3df..45ae8c64ca 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/User.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/persistence/model/User.java @@ -35,13 +35,6 @@ public class User { @JoinColumn(name = "organization_id", referencedColumnName = "id") private Organization organization; - // - - public User() { - super(); - } - - // public Long getId() { return id; } @@ -82,8 +75,6 @@ public class User { this.organization = organization; } - // - @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomMethodSecurityExpressionRoot.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomMethodSecurityExpressionRoot.java index dd9f6a5786..47a4472a93 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomMethodSecurityExpressionRoot.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomMethodSecurityExpressionRoot.java @@ -14,14 +14,11 @@ public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot i super(authentication); } - // public boolean isMember(Long OrganizationId) { final User user = ((MyUserPrincipal) this.getPrincipal()).getUser(); return user.getOrganization().getId().longValue() == OrganizationId.longValue(); } - // - @Override public Object getFilterObject() { return this.filterObject; @@ -46,5 +43,4 @@ public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot i public void setReturnObject(Object obj) { this.returnObject = obj; } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomPermissionEvaluator.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomPermissionEvaluator.java index d69e405b28..2e81859203 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomPermissionEvaluator.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/CustomPermissionEvaluator.java @@ -27,11 +27,8 @@ public class CustomPermissionEvaluator implements PermissionEvaluator { private boolean hasPrivilege(Authentication auth, String targetType, String permission) { for (final GrantedAuthority grantedAuth : auth.getAuthorities()) { - System.out.println("here " + grantedAuth); - if (grantedAuth.getAuthority().startsWith(targetType)) { - if (grantedAuth.getAuthority().contains(permission)) { - return true; - } + if (grantedAuth.getAuthority().startsWith(targetType) && grantedAuth.getAuthority().contains(permission)) { + return true; } } return false; diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MySecurityExpressionRoot.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MySecurityExpressionRoot.java index 8448ad9075..f3a3cbeb46 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MySecurityExpressionRoot.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MySecurityExpressionRoot.java @@ -15,6 +15,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations { + protected final Authentication authentication; private AuthenticationTrustResolver trustResolver; private RoleHierarchy roleHierarchy; @@ -30,8 +31,6 @@ public class MySecurityExpressionRoot implements MethodSecurityExpressionOperati public final String delete = "delete"; public final String admin = "administration"; - // - private Object filterObject; private Object returnObject; @@ -47,14 +46,11 @@ public class MySecurityExpressionRoot implements MethodSecurityExpressionOperati throw new RuntimeException("method hasAuthority() not allowed"); } - // public boolean isMember(Long OrganizationId) { final User user = ((MyUserPrincipal) this.getPrincipal()).getUser(); return user.getOrganization().getId().longValue() == OrganizationId.longValue(); } - // - @Override public final boolean hasAnyAuthority(String... authorities) { return hasAnyAuthorityName(null, authorities); @@ -136,7 +132,6 @@ public class MySecurityExpressionRoot implements MethodSecurityExpressionOperati private Set getAuthoritySet() { if (roles == null) { - roles = new HashSet(); Collection userAuthorities = authentication.getAuthorities(); if (roleHierarchy != null) { diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserDetailsService.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserDetailsService.java index c6514d6c05..dc845e05e1 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserDetailsService.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserDetailsService.java @@ -14,12 +14,6 @@ public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; - public MyUserDetailsService() { - super(); - } - - // API - @Override public UserDetails loadUserByUsername(final String username) { final User user = userRepository.findByUsername(username); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserPrincipal.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserPrincipal.java index 41741c64f4..afe92fb066 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserPrincipal.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/security/MyUserPrincipal.java @@ -16,14 +16,10 @@ public class MyUserPrincipal implements UserDetails { private final User user; - // - public MyUserPrincipal(User user) { this.user = user; } - // - @Override public String getUsername() { return user.getUsername(); @@ -36,7 +32,7 @@ public class MyUserPrincipal implements UserDetails { @Override public Collection getAuthorities() { - final List authorities = new ArrayList(); + final List authorities = new ArrayList<>(); for (final Privilege privilege : user.getPrivileges()) { authorities.add(new SimpleGrantedAuthority(privilege.getName())); } @@ -63,10 +59,7 @@ public class MyUserPrincipal implements UserDetails { return true; } - // - public User getUser() { return user; } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/web/MainController.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/web/MainController.java index beb12f7749..1908289f96 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/web/MainController.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/custom/web/MainController.java @@ -39,8 +39,6 @@ public class MainController { return foo; } - // - @PreAuthorize("hasAuthority('FOO_READ_PRIVILEGE')") @GetMapping("/foos") @ResponseBody @@ -48,8 +46,6 @@ public class MainController { return new Foo(name); } - // - @PreAuthorize("isMember(#id)") @GetMapping("/organizations/{id}") @ResponseBody @@ -64,5 +60,4 @@ public class MainController { public MyUserPrincipal retrieveUserDetails(@AuthenticationPrincipal MyUserPrincipal principal) { return principal; } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/IpApplication.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/IpApplication.java index b9a86fee3e..ca1d21505b 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/IpApplication.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/IpApplication.java @@ -3,11 +3,9 @@ package com.baeldung.roles.ip; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.PropertySource; @SpringBootApplication -@ComponentScan("com.baeldung.ip") @PropertySource("classpath:application-defaults.properties") public class IpApplication extends SpringBootServletInitializer { public static void main(String[] args) { diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/CustomIpAuthenticationProvider.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/CustomIpAuthenticationProvider.java index adcadb65e8..637af2301f 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/CustomIpAuthenticationProvider.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/CustomIpAuthenticationProvider.java @@ -1,10 +1,5 @@ package com.baeldung.roles.ip.config; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -15,13 +10,17 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + @Component public class CustomIpAuthenticationProvider implements AuthenticationProvider { - - Set whitelist = new HashSet(); + + Set whitelist = new HashSet<>(); public CustomIpAuthenticationProvider() { - super(); whitelist.add("11.11.11.11"); whitelist.add("127.0.0.1"); } @@ -30,18 +29,17 @@ public class CustomIpAuthenticationProvider implements AuthenticationProvider { public Authentication authenticate(Authentication auth) throws AuthenticationException { WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails(); String userIp = details.getRemoteAddress(); - if(! whitelist.contains(userIp)){ + if (!whitelist.contains(userIp)) { throw new BadCredentialsException("Invalid IP Address"); } final String name = auth.getName(); final String password = auth.getCredentials().toString(); - + if (name.equals("john") && password.equals("123")) { - List authorities =new ArrayList(); - authorities.add(new SimpleGrantedAuthority("ROLE_USER")); - return new UsernamePasswordAuthenticationToken(name, password, authorities); - } - else{ + List authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority("ROLE_USER")); + return new UsernamePasswordAuthenticationToken(name, password, authorities); + } else { throw new BadCredentialsException("Invalid username or password"); } } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/SecurityConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/SecurityConfig.java index 46ba62afb3..71c7bcccc6 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/SecurityConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/config/SecurityConfig.java @@ -8,7 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration -@EnableWebSecurity//(debug = true) +@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired @@ -22,7 +22,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { - // @formatter:off http.authorizeRequests() .antMatchers("/login").permitAll() // .antMatchers("/foos/**").hasIpAddress("11.11.11.11") @@ -30,7 +29,5 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .anyRequest().authenticated() .and().formLogin().permitAll() .and().csrf().disable(); - // @formatter:on } - } \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/web/MainController.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/web/MainController.java index 438b668c5f..6fa165433a 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/web/MainController.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/ip/web/MainController.java @@ -11,9 +11,8 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @Controller @@ -23,7 +22,7 @@ public class MainController { @Qualifier("springSecurityFilterChain") private Filter springSecurityFilterChain; - @RequestMapping(method = RequestMethod.GET, value = "/filters") + @GetMapping("/filters") @ResponseBody public void getFilters() { FilterChainProxy filterChainProxy = (FilterChainProxy) springSecurityFilterChain; @@ -32,11 +31,10 @@ public class MainController { .flatMap(chain -> chain.getFilters().stream()) .forEach(filter -> System.out.println(filter.getClass())); } - - @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + + @GetMapping("/foos/{id}") @ResponseBody public Foo findById(@PathVariable final long id, HttpServletRequest request) { return new Foo("Sample"); } - } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/CustomAuthenticationProvider.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/CustomAuthenticationProvider.java index 5168e64b4a..78bb18354b 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/CustomAuthenticationProvider.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/CustomAuthenticationProvider.java @@ -12,11 +12,11 @@ import org.springframework.security.core.userdetails.UserDetailsService; public class CustomAuthenticationProvider extends DaoAuthenticationProvider { private final UserRepository userRepository; + @SuppressWarnings("unused") private UserDetailsService userDetailsService; public CustomAuthenticationProvider(UserRepository userRepository, UserDetailsService userDetailsService){ - super(); this.setUserDetailsService(userDetailsService); this.userRepository = userRepository; } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyLogoutSuccessHandler.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyLogoutSuccessHandler.java index 23104e5292..0ee4707d1b 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyLogoutSuccessHandler.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyLogoutSuccessHandler.java @@ -2,7 +2,6 @@ package com.baeldung.roles.rolesauthorities; import java.io.IOException; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -15,7 +14,7 @@ import org.springframework.stereotype.Component; public class MyLogoutSuccessHandler implements LogoutSuccessHandler { @Override - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { final HttpSession session = request.getSession(); if (session != null) { session.removeAttribute("user"); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyUserDetailsService.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyUserDetailsService.java index 18230ba794..72fae18c09 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyUserDetailsService.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/MyUserDetailsService.java @@ -24,12 +24,6 @@ public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; - public MyUserDetailsService() { - super(); - } - - // API - @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { @@ -38,17 +32,20 @@ public class MyUserDetailsService implements UserDetailsService { if (user == null) { throw new UsernameNotFoundException("No user found with username: " + email); } - org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles())); - return userDetails; + return new org.springframework.security.core.userdetails.User(user.getEmail(), + user.getPassword(), + user.isEnabled(), + true, + true, + true, + getAuthorities(user.getRoles())); } catch (final Exception e) { throw new RuntimeException(e); } } - // UTIL - - private final Collection getAuthorities(Collection roles) { - List authorities = new ArrayList(); + private Collection getAuthorities(Collection roles) { + List authorities = new ArrayList<>(); for (Role role: roles) { authorities.add(new SimpleGrantedAuthority(role.getName())); authorities.addAll(role.getPrivileges() diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/RolesAuthoritiesApplication.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/RolesAuthoritiesApplication.java index d3e54b4303..72d655c051 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/RolesAuthoritiesApplication.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/RolesAuthoritiesApplication.java @@ -8,7 +8,7 @@ import org.springframework.context.annotation.Configuration; @Configuration @EnableAutoConfiguration -@ComponentScan("com.baeldung.rolesauthorities") +@ComponentScan("com.baeldung.roles.rolesauthorities") public class RolesAuthoritiesApplication extends SpringBootServletInitializer { public static void main(String[] args) { System.setProperty("spring.profiles.default", "rolesauthorities"); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/MvcConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/MvcConfig.java index 61394b6178..3dd60704f0 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/MvcConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/MvcConfig.java @@ -13,11 +13,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { - public MvcConfig() { - super(); - } - - // @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/SecurityConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/SecurityConfig.java index cb8476fcc7..9b7ccfd25b 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/SecurityConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/config/SecurityConfig.java @@ -31,10 +31,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private LogoutSuccessHandler myLogoutSuccessHandler; - public SecurityConfig() { - super(); - } - @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authProvider()); @@ -50,7 +46,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { - // @formatter:off http .csrf().disable() .authorizeRequests() @@ -69,11 +64,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .logoutSuccessUrl("/logout.html?logSucc=true") .deleteCookies("JSESSIONID") .permitAll(); - // @formatter:on } - // beans - @Bean public DaoAuthenticationProvider authProvider() { final CustomAuthenticationProvider authProvider @@ -86,5 +78,4 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { public PasswordEncoder encoder() { return new BCryptPasswordEncoder(11); } - } \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Privilege.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Privilege.java index 507beaffa8..1e444faf2d 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Privilege.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Privilege.java @@ -21,16 +21,12 @@ public class Privilege { private Collection roles; public Privilege() { - super(); } public Privilege(String name) { - super(); this.name = name; } - // - public Long getId() { return id; } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Role.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Role.java index a284d92090..031c9f0828 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Role.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/Role.java @@ -27,16 +27,12 @@ public class Role { private String name; public Role() { - super(); } public Role(String name) { - super(); this.name = name; } - // - public Long getId() { return id; } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/User.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/User.java index ebf0c9b310..cb90947ed6 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/User.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/model/User.java @@ -35,14 +35,11 @@ public class User { private boolean isUsing2FA; - // - @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) private Collection roles; public User() { - super(); this.enabled = false; } @@ -143,5 +140,4 @@ public class User { .append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", roles=").append(roles).append("]"); return builder.toString(); } - } \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/persistence/SetupDataLoader.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/persistence/SetupDataLoader.java index 140fc56e53..bf3245a391 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/persistence/SetupDataLoader.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/rolesauthorities/persistence/SetupDataLoader.java @@ -74,7 +74,7 @@ public class SetupDataLoader implements ApplicationListener privileges) { + public Role createRoleIfNotFound(String name, Collection privileges) { Role role = roleRepository.findByName(name); if (role == null) { role = new Role(name); @@ -93,5 +93,4 @@ public class SetupDataLoader implements ApplicationListener "ROLE_USER".equals(r) && LocalDateTime.now().getMinute() % 2 != 0).findAny().map(s -> ACCESS_DENIED).orElseGet(() -> ACCESS_ABSTAIN); + return authentication.getAuthorities() + .stream() + .map(GrantedAuthority::getAuthority) + .filter(r -> "ROLE_USER".equals(r) && LocalDateTime.now().getMinute() % 2 != 0) + .findAny() + .map(s -> ACCESS_DENIED) + .orElse(ACCESS_ABSTAIN); } } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java index 402065129f..4133d5fdb8 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/VoterMvcConfig.java @@ -4,10 +4,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -/** - * Created by ambrusadrianz on 30/09/2016. - */ - @Configuration public class VoterMvcConfig implements WebMvcConfigurer { @Override diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java index 1a6d1b8235..5141e1af7c 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/WebSecurityConfig.java @@ -22,28 +22,46 @@ import java.util.List; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - // @formatter: off - auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("pass")).roles("USER").and().withUser("admin").password(passwordEncoder().encode("pass")).roles("ADMIN"); - // @formatter: on + auth + .inMemoryAuthentication() + .withUser("user") + .password(passwordEncoder().encode("pass")) + .roles("USER") + .and() + .withUser("admin") + .password(passwordEncoder().encode("pass")) + .roles("ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { - // @formatter: off http - // needed so our login could work - .csrf().disable().authorizeRequests().anyRequest().authenticated().accessDecisionManager(accessDecisionManager()).and().formLogin().permitAll().and().logout().permitAll() - .deleteCookies("JSESSIONID").logoutSuccessUrl("/login"); - // @formatter: on + .csrf() + .disable() + .authorizeRequests() + .anyRequest() + .authenticated() + .accessDecisionManager(accessDecisionManager()) + .and() + .formLogin() + .permitAll() + .and() + .logout() + .permitAll() + .deleteCookies("JSESSIONID").logoutSuccessUrl("/login"); } @Bean public AccessDecisionManager accessDecisionManager() { - // @formatter: off - List> decisionVoters = Arrays.asList(new WebExpressionVoter(), new RoleVoter(), new AuthenticatedVoter(), new MinuteBasedVoter()); - // @formatter: on + List> decisionVoters = Arrays.asList( + new WebExpressionVoter(), + new RoleVoter(), + new AuthenticatedVoter(), + new MinuteBasedVoter()); + return new UnanimousBased(decisionVoters); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/XmlSecurityConfig.java b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/XmlSecurityConfig.java index 0ef2ef51c7..17a63142ea 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/XmlSecurityConfig.java +++ b/spring-security-modules/spring-security-web-boot-1/src/main/java/com/baeldung/roles/voter/XmlSecurityConfig.java @@ -1,12 +1,6 @@ package com.baeldung.roles.voter; -/** - * Created by ambrusadrianz on 09/10/2016. - */ // @Configuration // @ImportResource({ "classpath:spring-security-custom-voter.xml" }) public class XmlSecurityConfig { - public XmlSecurityConfig() { - super(); - } } diff --git a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/relationships/SpringDataWithSecurityIntegrationTest.java b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/relationships/SpringDataWithSecurityIntegrationTest.java index 54120650d9..10c32de5d7 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/relationships/SpringDataWithSecurityIntegrationTest.java +++ b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/relationships/SpringDataWithSecurityIntegrationTest.java @@ -36,12 +36,15 @@ import static org.springframework.util.Assert.isTrue; @ContextConfiguration @DirtiesContext public class SpringDataWithSecurityIntegrationTest { - AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); - @Autowired - private ServletContext servletContext; + private static UserRepository userRepository; private static TweetRepository tweetRepository; + @Autowired + private ServletContext servletContext; + + AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); + @Before public void testInit() { ctx.register(AppConfig.class); diff --git a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/ApplicationLiveTest.java b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/ApplicationLiveTest.java index 5a040b8dea..56f87e8aee 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/ApplicationLiveTest.java +++ b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/ApplicationLiveTest.java @@ -13,7 +13,7 @@ import io.restassured.specification.RequestSpecification; import org.junit.Test; import org.springframework.http.MediaType; -// In order to execute these tests, com.baeldung.custom.Application needs to be running. +// In order to execute these tests, com.baeldung.roles.custom.Application needs to be running. public class ApplicationLiveTest { @Test @@ -36,8 +36,6 @@ public class ApplicationLiveTest { assertTrue(response.asString().contains("id")); } - // - @Test public void givenUserMemberInOrganization_whenGetOrganization_thenOK() { final Response response = givenAuth("john", "123").get("http://localhost:8082/organizations/1"); @@ -51,8 +49,6 @@ public class ApplicationLiveTest { assertEquals(403, response.getStatusCode()); } - // - @Test public void givenDisabledSecurityExpression_whenGetFooByName_thenError() { final Response response = givenAuth("john", "123").get("http://localhost:8082/foos?name=sample"); @@ -60,7 +56,6 @@ public class ApplicationLiveTest { assertTrue(response.asString().contains("method hasAuthority() not allowed")); } - // private RequestSpecification givenAuth(String username, String password) { return RestAssured.given().log().uri().auth().form(username, password, new FormAuthConfig("/login","username","password")); } diff --git a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/CustomUserDetailsServiceIntegrationTest.java b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/CustomUserDetailsServiceIntegrationTest.java index df7645150f..adf385140f 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/CustomUserDetailsServiceIntegrationTest.java +++ b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/CustomUserDetailsServiceIntegrationTest.java @@ -9,7 +9,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import org.apache.http.HttpHeaders; import com.baeldung.roles.custom.Application; import com.baeldung.roles.custom.persistence.model.Foo; -import org.junit.jupiter.api.Test; +import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -82,8 +82,7 @@ public class CustomUserDetailsServiceIntegrationTest { private static String asJsonString(final Object obj) throws Exception { final ObjectMapper mapper = new ObjectMapper(); - final String jsonContent = mapper.writeValueAsString(obj); - return jsonContent; + return mapper.writeValueAsString(obj); } } diff --git a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/IpLiveTest.java b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/IpLiveTest.java index 2d0e2e5402..a57f9e675f 100644 --- a/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/IpLiveTest.java +++ b/spring-security-modules/spring-security-web-boot-1/src/test/java/com/baeldung/roles/web/IpLiveTest.java @@ -8,7 +8,7 @@ import io.restassured.response.Response; import org.junit.Test; -// In order to execute these tests, com.baeldung.ip.IpApplication needs to be running. +// In order to execute these tests, com.baeldung.roles.ip.IpApplication needs to be running. public class IpLiveTest { @Test diff --git a/spring-security-modules/spring-security-web-boot-3/README.md b/spring-security-modules/spring-security-web-boot-3/README.md new file mode 100644 index 0000000000..aeba397f40 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/README.md @@ -0,0 +1,11 @@ +## Spring Boot Security MVC + +This module contains articles about Spring Security with Spring MVC in Boot applications + +### The Course +The "REST With Spring" Classes: http://github.learnspringsecurity.com + +### Relevant Articles: + +- [TLS Setup in Spring](https://www.baeldung.com/spring-tls-setup) +- More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-2) diff --git a/spring-security-modules/spring-security-web-boot-3/pom.xml b/spring-security-modules/spring-security-web-boot-3/pom.xml new file mode 100644 index 0000000000..a6e2b48d75 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + spring-security-web-boot-3 + 0.0.1-SNAPSHOT + spring-security-web-boot-3 + jar + Spring Security MVC Boot - 3 + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/HomeController.java b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/HomeController.java new file mode 100644 index 0000000000..c72821cc9b --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/HomeController.java @@ -0,0 +1,16 @@ +package com.baeldung.tls; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HomeController { + + @GetMapping("/baeldung") + public ResponseEntity welcome() { + return new ResponseEntity<>("tls/baeldung", HttpStatus.OK); + } + +} diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/SecurityConfig.java b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/SecurityConfig.java new file mode 100644 index 0000000000..63b59b8cc8 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/SecurityConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.tls; + +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/**") + .permitAll(); + } +} diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/TLSEnabledApplication.java b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/TLSEnabledApplication.java new file mode 100644 index 0000000000..62ba77d769 --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/java/com/baeldung/tls/TLSEnabledApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.tls; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +public class TLSEnabledApplication { + + public static void main(String... args) { + SpringApplication application = new SpringApplication(TLSEnabledApplication.class); + application.setAdditionalProfiles("tls"); + application.run(args); + } +} diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/resources/application-tls.properties b/spring-security-modules/spring-security-web-boot-3/src/main/resources/application-tls.properties new file mode 100644 index 0000000000..002d702eab --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/resources/application-tls.properties @@ -0,0 +1,23 @@ + +server.port=8443 + +# enable/disable https +server.ssl.enabled=true +# keystore format +server.ssl.key-store-type=PKCS12 +# keystore location +server.ssl.key-store=classpath:keystore/keystore.p12 +# keystore password +server.ssl.key-store-password=changeit +server.ssl.key-alias=baeldung +# SSL protocol to use +server.ssl.protocol=TLS +# Enabled SSL protocols +server.ssl.enabled-protocols=TLSv1.2 + +#server.ssl.client-auth=need + +#trust store location +#server.ssl.trust-store=classpath:keystore/truststore.p12 +#trust store password +#server.ssl.trust-store-password=changeit \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/resources/keystore/baeldung.cer b/spring-security-modules/spring-security-web-boot-3/src/main/resources/keystore/baeldung.cer new file mode 100644 index 0000000000..1a6bb4d49b --- /dev/null +++ b/spring-security-modules/spring-security-web-boot-3/src/main/resources/keystore/baeldung.cer @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExzCCAq+gAwIBAgIEbh/WszANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDEwls +b2NhbGhvc3QwHhcNMjEwMzIxMDgzMzU3WhcNMzEwMzE5MDgzMzU3WjAUMRIwEAYD +VQQDEwlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCD +QWvAEewDE+vFFqYPgXFJ94bMgPZT6qdb17DkWWbL2jV5QENbSYTLAPNQ1TGUgKhj +t1LCHpooLwWIo6xvhK/qZYjh3YonSIe8Eo0fBCDoZpLO+Vp0us22NBgLOYH8hvAm +zEvPXdSZo5Qkeaqjwd6kB/z083y8OL+Civ0ARXoLsn7CFslKfZp2o/aebH6i/T+3 +hWVqasIIMtfNUrxE/pnOnV8aSAt24jcm/VxbtheqIzmcOPlCXSP1RAmFez6tJsNu +2dbUhaeOf95RCaM6a43soEvLvooGa/uqBPsRojg5WEFGf7Tc7pzB+BtALwRmHAqr +hiYjVv329QGZ+g8dADBvvqvGpGysy+X0LxixvIP14KdCqG8uMYmw5cBTJHc23AHV +iP+JsfDtdu+bzZeOZmhSsv4M3DZ1QPHEX+zCnotE+SeycqEr+3SaJELyjCB1twFT +pCRCQGWFKYCRwhjQ1vGY7qhD6ZDn30a96xAlPS+T35pA01rNgORJi8j9sf3oiwEe +oPQOecgFHdua5drHJ78j7MUz/Gvj02GnwKnBKbMYDGeBKJWm0ir4MxoU7HPaDwLj +jofXgIz+CMXkp+9arVu5IsZwL2MKNZ4fiM+VWZg9R73CAVpKvs6dTlQXe++DCaOr +XGiQeCPPpIC74vqWhAHuzPncGJndHlmXYGLhi0sk0wIDAQABoyEwHzAdBgNVHQ4E +FgQUhW4a3uWREJoTxodyD5u7i7mCaacwDQYJKoZIhvcNAQELBQADggIBAD/Qfkot +qklQr4r7eoHtyFCGozfZvsPwEediZORkycU/fCZozdVh95ebt2/N/jw7RlNhv+t+ +HahMoiXbLX2RUrqM/2X5U7BbxIpy3XjhcEYTJudqFfCxDQfxD1bFrWHygQzAanOb +sPHkcEt3tu2suV2YsJpHry/1BMo83WAoTgw/3dFtJ7oEoi/LaI03v9Qlp0+hLfA5 +zwyuuRqFn24FRvdWHX5GqAweF+WUdmmlkiJiKu2RtQsPoN7ITvZQs9t4l0zZ8w2v +QV0YdhWYLkS3g53oyOP8T5YlCFGuUOyo433hRyrzaxj3aFDkMbNrX9REB9v8Iz7X +aFsmLDJsfT5Spovz68HCIMDW1Sl1WqVkNN2V3Rwt72bn7DEbKZzGW9RC5eXEW1Zw +46XeYOVdEjzl/l623moWC5ZTlwPF1qRDaoZXT/1d1eAJE8ZBHm1YjwgDD5aFvylG +0OT1qWD5gx3nOmAbBk1e3r8ESMo9k29/4hycUUUgtFuWtBwBaY/O/4YoLx59wbpL +rFR/zjKIdYFj0AM2ABTgrG7v5pEhjLTnzjc+mZV7hJCBvB+bbC5vvfDg0K7lQUpJ +ruIPvqKfJyuTwkKmoTF5jmG04jwUDtA5iGUB3U3QiQ8zcbTiVRptXLEQDYw/bzDk +0fd4xTbok1ygI7wJ/KRyMvFXdbTKSvVu/tnM +-----END CERTIFICATE----- diff --git a/spring-security-modules/spring-security-web-boot-3/src/main/resources/keystore/keystore.p12 b/spring-security-modules/spring-security-web-boot-3/src/main/resources/keystore/keystore.p12 new file mode 100644 index 0000000000..6f0d9c508c Binary files /dev/null and b/spring-security-modules/spring-security-web-boot-3/src/main/resources/keystore/keystore.p12 differ diff --git a/spring-web-modules/spring-boot-jsp/README.md b/spring-web-modules/spring-boot-jsp/README.md new file mode 100644 index 0000000000..535f86531d --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Spring Boot With JavaServer Pages (JSP)](https://www.baeldung.com/spring-boot-jsp) diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/longpolling/client/LongPollingBakeryClient.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/longpolling/client/LongPollingBakeryClient.java new file mode 100644 index 0000000000..be6a3ac54d --- /dev/null +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/longpolling/client/LongPollingBakeryClient.java @@ -0,0 +1,42 @@ +package com.baeldung.longpolling.client; + +import io.netty.handler.timeout.ReadTimeoutException; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.WebClient; + +import java.time.Duration; + +@Component +public class LongPollingBakeryClient { + + public String callBakeWithRestTemplate(RestTemplateBuilder restTemplateBuilder) { + RestTemplate restTemplate = restTemplateBuilder + .setConnectTimeout(Duration.ofSeconds(10)) + .setReadTimeout(Duration.ofSeconds(10)) + .build(); + + try { + return restTemplate.getForObject("/api/bake/cookie?bakeTime=1000", String.class); + } catch (ResourceAccessException e) { + throw e; + } + } + + public String callBakeWithWebClient() { + WebClient webClient = WebClient.create(); + + try { + return webClient.get() + .uri("/api/bake/cookie?bakeTime=1000") + .retrieve() + .bodyToFlux(String.class) + .timeout(Duration.ofSeconds(10)) + .blockFirst(); + } catch (ReadTimeoutException e) { + throw e; + } + } +} diff --git a/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/longpolling/controller/BakeryController.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/longpolling/controller/BakeryController.java new file mode 100644 index 0000000000..51dfb6bbf2 --- /dev/null +++ b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/longpolling/controller/BakeryController.java @@ -0,0 +1,49 @@ +package com.baeldung.longpolling.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.async.DeferredResult; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static java.lang.String.format; + +/** + * Long polling controller example. + */ +@RestController +@RequestMapping("/api") +public class BakeryController { + private final static Logger LOG = LoggerFactory.getLogger(BakeryController.class); + private final static Long LONG_POLLING_TIMEOUT = 5000L; + + private ExecutorService bakers; + + public BakeryController() { + bakers = Executors.newFixedThreadPool(5); + } + + @GetMapping("/bake/{bakedGood}") + public DeferredResult publisher(@PathVariable String bakedGood, @RequestParam Integer bakeTime) { + + DeferredResult output = new DeferredResult<>(LONG_POLLING_TIMEOUT); + + bakers.execute(() -> { + try { + Thread.sleep(bakeTime); + output.setResult(format("Bake for %s complete and order dispatched. Enjoy!", bakedGood)); + } catch (Exception e) { + output.setErrorResult("Something went wrong with your order!"); + } + }); + + output.onTimeout(() -> output.setErrorResult("the bakery is not responding in allowed time")); + return output; + } +} diff --git a/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/longpolling/integration/BakeryControllerIntegrationTest.java b/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/longpolling/integration/BakeryControllerIntegrationTest.java new file mode 100644 index 0000000000..abc40d72ca --- /dev/null +++ b/spring-web-modules/spring-rest-http-2/src/test/com/baeldung/longpolling/integration/BakeryControllerIntegrationTest.java @@ -0,0 +1,72 @@ +package com.baeldung.longpolling.integration; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockAsyncContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.io.IOException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; + +@AutoConfigureMockMvc +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class BakeryControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void givenDeferredResultTimesOut_ThenErrorResponseIsRecieved() throws Exception { + MvcResult asyncListener = mockMvc + .perform(MockMvcRequestBuilders.get("/api/bake/cookie?bakeTime=6000")) + .andExpect(request().asyncStarted()) + .andReturn(); + + enableTimeout(asyncListener); + + String response = mockMvc + .perform(asyncDispatch(asyncListener)) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response) + .isEqualTo("the bakery is not responding in allowed time"); + } + + @Test + public void givenDeferredResultSuccessful_ThenSuccessResponseIsRecieved() throws Exception { + MvcResult asyncListener = mockMvc + .perform(MockMvcRequestBuilders.get("/api/bake/cookie?bakeTime=1000")) + .andExpect(request().asyncStarted()) + .andReturn(); + + String response = mockMvc + .perform(asyncDispatch(asyncListener)) + .andReturn() + .getResponse() + .getContentAsString(); + + assertThat(response) + .isEqualTo("Bake for cookie complete and order dispatched. Enjoy!"); + } + + private static void enableTimeout(MvcResult asyncListener) throws IOException { + ((MockAsyncContext) asyncListener + .getRequest() + .getAsyncContext()) + .getListeners() + .get(0) + .onTimeout(null); + } +} diff --git a/spring-web-modules/spring-rest-http/pom.xml b/spring-web-modules/spring-rest-http/pom.xml index 422bcd32f7..94d1be7814 100644 --- a/spring-web-modules/spring-rest-http/pom.xml +++ b/spring-web-modules/spring-rest-http/pom.xml @@ -24,6 +24,10 @@ org.springframework.boot spring-boot-starter-validation + + org.springframework.boot + spring-boot-starter-webflux + org.springframework spring-oxm diff --git a/spring-web-modules/spring-thymeleaf-3/README.md b/spring-web-modules/spring-thymeleaf-3/README.md index 048b48d39f..76c54d3885 100644 --- a/spring-web-modules/spring-thymeleaf-3/README.md +++ b/spring-web-modules/spring-thymeleaf-3/README.md @@ -10,3 +10,4 @@ This module contains articles about Spring with Thymeleaf - [Conditional CSS Classes in Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-conditional-css-classes) - [Using Hidden Inputs with Spring and Thymeleaf](https://www.baeldung.com/spring-thymeleaf-hidden-inputs) - [Thymeleaf Variables](https://www.baeldung.com/thymeleaf-variables) +- [Displaying Error Messages with Thymeleaf in Spring](https://www.baeldung.com/spring-thymeleaf-error-messages) diff --git a/spring-web-modules/spring-thymeleaf-3/pom.xml b/spring-web-modules/spring-thymeleaf-3/pom.xml index 6dd1267e8a..6a46dca117 100644 --- a/spring-web-modules/spring-thymeleaf-3/pom.xml +++ b/spring-web-modules/spring-thymeleaf-3/pom.xml @@ -26,7 +26,15 @@ org.springframework.boot spring-boot-starter-thymeleaf - + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + org.springframework.boot spring-boot-starter-test diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/User.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/User.java new file mode 100644 index 0000000000..a6923287af --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/User.java @@ -0,0 +1,82 @@ +package com.baeldung.thymeleaf.errors; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @NotEmpty(message = "User's name cannot be empty.") + @Size(min = 5, max = 250) + private String fullName; + + @NotEmpty(message = "User's email cannot be empty.") + @Size(min = 7, max = 320) + private String email; + + @NotNull(message = "User's age cannot be null.") + @Min(value = 18) + private Integer age; + + private String country; + + private String phoneNumber; + + public Long getId() { + return id; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserController.java new file mode 100644 index 0000000000..92e67dc6a8 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserController.java @@ -0,0 +1,46 @@ +package com.baeldung.thymeleaf.errors; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +@Controller +public class UserController { + + @Autowired + private UserRepository repository; + + @Autowired + private UserValidationService validationService; + + @GetMapping("/add") + public String showAddUserForm(User user) { + return "errors/addUser"; + } + + @PostMapping("/add") + public String addUser(@Valid User user, BindingResult result, Model model) { + + String err = validationService.validateUser(user); + + if (!err.isEmpty()) { + ObjectError error = new ObjectError("globalError", err); + result.addError(error); + } + + if (result.hasErrors()) { + return "errors/addUser"; + } + + repository.save(user); + model.addAttribute("users", repository.findAll()); + return "errors/home"; + } + +} diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserRepository.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserRepository.java new file mode 100644 index 0000000000..5e0e322728 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.thymeleaf.errors; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends JpaRepository { +} diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserValidationService.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserValidationService.java new file mode 100644 index 0000000000..a2de4e2ed4 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/errors/UserValidationService.java @@ -0,0 +1,22 @@ +package com.baeldung.thymeleaf.errors; + +import org.springframework.stereotype.Service; + +@Service +public class UserValidationService { + + public String validateUser(User user) { + + String message = ""; + + if (user.getCountry() != null && user.getPhoneNumber() != null) { + if (user.getCountry() + .equalsIgnoreCase("India") + && !user.getPhoneNumber() + .startsWith("91")) { + message = "Phone number is invalid for " + user.getCountry(); + } + } + return message; + } +} diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties b/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties new file mode 100644 index 0000000000..75770808da --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/errors/addUser.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/errors/addUser.html new file mode 100644 index 0000000000..4e37dc45ce --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/errors/addUser.html @@ -0,0 +1,77 @@ + + + + + + +Displaying Error Messages with Thymeleaf + + +
+
+

Add a Record

+
+
+ +
    +
  • +
+
+
+ +

+

+
+ +

Invalid Age

+
+
+ +

+

+
+ +

+

+
+

Global errors:

+

+

+

All errors in place:

+
+
    +
  • +
+
+ +
+

This is outside the form:

+

Errors on a single field:

+
+

All errors:

+
    +
  • +
+
+
+ + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/errors/home.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/errors/home.html new file mode 100644 index 0000000000..4f63be5dc6 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/errors/home.html @@ -0,0 +1,34 @@ + + + + + +Displaying Error Messages with Thymeleaf + + +
+
+

Users

+ + + + + + + + + + + +
IDFull nameEmailAgeCountryPhone Number
+ + + + + +
+
+
+ + \ No newline at end of file diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index ded3e9e26d..90898ebb3f 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -136,7 +136,6 @@ 2.8.2 2.0.0 2.22.0 - 1.6.0 5.0.1.RELEASE 3.0.0-M3 diff --git a/testing-modules/junit5-migration/pom.xml b/testing-modules/junit5-migration/pom.xml index e3ef21f506..bab7bc0406 100644 --- a/testing-modules/junit5-migration/pom.xml +++ b/testing-modules/junit5-migration/pom.xml @@ -47,23 +47,6 @@ true - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - java - - - - - com.baeldung.TestLauncher - - - @@ -71,7 +54,6 @@ 1.2.0 5.2.0 2.21.0 - 1.6.0 diff --git a/testing-modules/test-containers/pom.xml b/testing-modules/test-containers/pom.xml index 1946b7306f..2280a89b4a 100644 --- a/testing-modules/test-containers/pom.xml +++ b/testing-modules/test-containers/pom.xml @@ -79,23 +79,6 @@ true - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - - java - - - - - com.baeldung.TestLauncher - - -