Merge remote-tracking branch 'upstream/master'

This commit is contained in:
mcasari 2023-09-23 16:46:14 +02:00
commit 91c0a3ceb2
29 changed files with 367 additions and 63 deletions

View File

@ -4,7 +4,7 @@ This module contains articles about Simple Storage Service (S3) on AWS
### Relevant articles
- [AWS S3 with Java](https://www.baeldung.com/aws-s3-java)
- [AWS S3 with Java](https://www.baeldung.com/java-aws-s3)
- [Multipart Uploads in Amazon S3 with Java](https://www.baeldung.com/aws-s3-multipart-upload)
- [Using the JetS3t Java Client With Amazon S3](https://www.baeldung.com/jets3t-amazon-s3)
- [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists)

View File

@ -1 +1,2 @@
## Relevant Articles
## Relevant Articles
- [Sequenced Collections in Java 21](https://www.baeldung.com/java-21-sequenced-collections)

View File

@ -5,4 +5,5 @@
- [Parsing Date Strings with Varying Formats](https://www.baeldung.com/java-parsing-dates-many-formats)
- [How Many Days Are There in a Particular Month of a Given Year?](https://www.baeldung.com/days-particular-month-given-year)
- [Difference Between Instant and LocalDateTime](https://www.baeldung.com/java-instant-vs-localdatetime)
- [Add Minutes to a Time String in Java](https://www.baeldung.com/java-string-time-add-mins)
- [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1)

View File

@ -3,9 +3,11 @@ package com.baeldung.dateapi;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
@ -19,7 +21,7 @@ public class JavaDurationUnitTest {
LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));
long seconds = Duration.between(initialTime, finalTime)
.getSeconds();
.getSeconds();
assertThat(seconds).isEqualTo(30);
}
@ -34,6 +36,22 @@ public class JavaDurationUnitTest {
assertThat(seconds).isEqualTo(30);
}
@Test
public void givenADuration_whenCallingisZeroAndisNegative_thenGetExpectedResult() {
LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2020-01-01T12:00:00");
assertFalse(Duration.between(start, end)
.isNegative());
assertTrue(Duration.between(end, start)
.isNegative());
LocalDateTime theTime = LocalDateTime.parse("2023-09-09T08:00:00");
assertTrue(Duration.between(theTime, theTime)
.isZero());
assertFalse(Duration.between(theTime, theTime)
.isNegative());
}
@Test
public void test2() {
Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
@ -53,17 +71,17 @@ public class JavaDurationUnitTest {
assertEquals(1, fromMinutes.toHours());
assertEquals(120, duration.plusSeconds(60)
.getSeconds());
.getSeconds());
assertEquals(30, duration.minusSeconds(30)
.getSeconds());
.getSeconds());
assertEquals(120, duration.plus(60, ChronoUnit.SECONDS)
.getSeconds());
.getSeconds());
assertEquals(30, duration.minus(30, ChronoUnit.SECONDS)
.getSeconds());
.getSeconds());
Duration fromChar1 = Duration.parse("P1DT1H10M10.5S");
Duration fromChar2 = Duration.parse("PT10M");
}
}
}

View File

@ -5,4 +5,5 @@
- [Sorting a HashSet in Java](https://www.baeldung.com/java-sort-hashset)
- [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set)
- [Cartesian Product of Any Number of Sets in Java](https://www.baeldung.com/java-cartesian-product-sets)
- [How to Get Index of an Item in Java Set](https://www.baeldung.com/java-set-element-find-index)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set)

View File

@ -5,4 +5,5 @@
- [Java Concurrent HashSet Equivalent to ConcurrentHashMap](https://www.baeldung.com/java-concurrent-hashset-concurrenthashmap)
- [Reading and Writing With a ConcurrentHashMap](https://www.baeldung.com/concurrenthashmap-reading-and-writing)
- [ArrayBlockingQueue vs. LinkedBlockingQueue](https://www.baeldung.com/java-arrayblockingqueue-vs-linkedblockingqueue)
- [Difference Between Hashtable and ConcurrentHashMap in Java](https://www.baeldung.com/java-hashtable-vs-concurrenthashmap)
- [[<-- Prev]](/core-java-modules/core-java-concurrency-collections)

View File

@ -12,4 +12,4 @@ This module contains articles about inheritance in Java
- [Guide to Inheritance in Java](https://www.baeldung.com/java-inheritance)
- [Object Type Casting in Java](https://www.baeldung.com/java-type-casting)
- [Variable and Method Hiding in Java](https://www.baeldung.com/java-variable-method-hiding)
- [Inner Classes Vs. Subclasses in Java](https://www.baeldung.com/java-inner-classes-vs-subclasses)
- [Inner Classes vs. Subclasses in Java](https://www.baeldung.com/java-inner-classes-vs-subclasses)

View File

@ -2,3 +2,4 @@
- [Difference Between parallelStream() and stream().parallel() in Java](https://www.baeldung.com/java-parallelstream-vs-stream-parallel)
- [Working With Empty Stream in Java](https://www.baeldung.com/java-empty-stream)
- [Aggregate Runtime Exceptions in Java Streams](https://www.baeldung.com/java-streams-aggregate-exceptions)
- [Streams vs. Loops in Java](https://www.baeldung.com/java-streams-vs-loops)

View File

@ -10,4 +10,5 @@
- [Guide to Splitting a String by Whitespace in Java](https://www.baeldung.com/java-splitting-a-string-by-whitespace)
- [Check if the First Letter of a String Is a Number](https://www.baeldung.com/java-check-if-string-starts-with-number)
- [Print “” Quotes Around a String in Java](https://www.baeldung.com/java-string-print-quotes)
- [Remove Punctuation From a String in Java](https://www.baeldung.com/java-remove-punctuation-from-string)
- [Remove Punctuation From a String in Java](https://www.baeldung.com/java-remove-punctuation-from-string)
- [Replacing Single Quote with \ in Java String](https://www.baeldung.com/java-replacing-single-quote-string)

View File

@ -2,3 +2,4 @@
- [Run a Java main Method Using Gradle](https://www.baeldung.com/gradle-run-java-main)
- [Finding Unused Gradle Dependencies](https://www.baeldung.com/gradle-finding-unused-dependencies)
- [Intro to Gradle Lint Plugin](https://www.baeldung.com/java-gradle-lint-intro)

View File

@ -114,7 +114,7 @@
<module>java-mongodb</module>
<module>questdb</module>
<module>neo4j</module>
<module>rethinkdb</module>
<!--<module>rethinkdb</module>--> <!-- JAVA-25297 -->
<module>scylladb</module>
<module>spring-data-cassandra-2</module>
<module>spring-data-jpa-repo-3</module>

View File

@ -2,3 +2,4 @@
- [Using Test Containers With Spring Data Cassandra](https://www.baeldung.com/spring-data-cassandra-test-containers)
- [Cassandra Object Mapping with DataStax Java Driver](https://www.baeldung.com/cassandra-object-mapping-datastax-java-driver)
- [Query With IN Clause in Spring Data Cassandra](https://www.baeldung.com/spring-cassandra-query-in-clause)

View File

@ -0,0 +1,4 @@
FROM couchbase/server:community-5.0.1
COPY configure.sh /configure.sh
CMD ["/configure.sh"]

View File

@ -0,0 +1,106 @@
#!/bin/bash
function retry() {
for i in $(seq 1 10); do
$1 "$2"
if [[ $? == 0 ]]; then
return 0
fi
sleep 1
done
return 1
}
function bucketCreate(){
couchbase-cli bucket-create -c localhost -u Administrator -p password \
--bucket="$1" \
--bucket-type=couchbase \
--bucket-ramsize=512 \
--bucket-replica=1 \
--wait
if [[ $? != 0 ]]; then
return 1
fi
}
function userCreate(){
createOutput=$(couchbase-cli user-manage -c localhost -u Administrator -p password \
--set --rbac-username "$1" --rbac-password "$1" \
--roles admin --auth-domain local)
if [[ $? != 0 ]]; then
echo $createOutput >&2
return 1
fi
}
function clusterUp(){
# wait for service to come up
until $(curl --output /dev/null --silent --head --fail http://localhost:8091); do
printf '.'
sleep 1
done
# initialize cluster
initOutput=$(couchbase-cli cluster-init -c localhost \
--cluster-username=Administrator \
--cluster-password=password \
--cluster-port=8091 \
--services=data,index,query,fts \
--cluster-ramsize=1024 \
--cluster-index-ramsize=256 \
--cluster-fts-ramsize=256 \
--index-storage-setting=default)
if [[ $? != 0 ]]; then
echo $initOutput >&2
return 1
fi
}
function main(){
set -ex
echo "Couchbase UI :8091"
echo "Couchbase logs /opt/couchbase/var/lib/couchbase/logs"
./entrypoint.sh couchbase-server &
if [[ $? != 0 ]]; then
echo "Couchbase startup failed. Exiting." >&2
exit 1
fi
clusterUp
if [[ $? != 0 ]]; then
echo "Cluster init failed. Exiting." >&2
exit 1
fi
retry userCreate baeldung
if [[ $? != 0 ]]; then
echo "User create failed. Exiting." >&2
exit 1
fi
retry userCreate baeldung2
if [[ $? != 0 ]]; then
echo "User create failed. Exiting." >&2
exit 1
fi
retry bucketCreate baeldung
if [[ $? != 0 ]]; then
echo "Bucket create failed. Exiting." >&2
exit 1
fi
retry bucketCreate baeldung2
if [[ $? != 0 ]]; then
echo "Bucket create failed. Exiting." >&2
exit 1
fi
set +ex
# entrypoint.sh launches the server but since config.sh is pid 1 we keep it
# running so that the docker container does not exit.
wait
}
main

View File

@ -0,0 +1,14 @@
#!/bin/bash
# setup
set -ex
docker rm couchbase_container -f
# main
docker build -t couchbase_image .
# cleanup
set +ex
# run
docker run -d --name couchbase_container -p 8091-8096:8091-8096 -p 11210-11211:11210-11211 couchbase_image

View File

@ -12,16 +12,10 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution
/**
* This LiveTest requires:
*
* 1- Couchbase instance running (e.g. with `docker run -d --name db -p 8091-8096:8091-8096 -p 11210-11211:11210-11211 couchbase`)
*
*
* 2- Couchbase configured with (we can use the console in localhost:8091):
*
* 2.1- Buckets: named 'baeldung' and 'baeldung2'
*
* 2.2- Security: users 'baeldung' and 'baeldung2'. Note: in newer versions an empty password is not allowed, then we have to change the passwords in the project)
*
* 2.3- Spacial View: Add new spacial view (in Index tab) in document 'campus_spatial', view 'byLocation' with the following function:
* 1- Couchbase 5 instance Running and Configured.
* It's enough to execute the "dockerbuild.sh" script in the test/docker folder.
*
* 2.1- Spacial View: Add new spacial view (in Index tab) in document 'campus_spatial', view 'byLocation' with the following function:
* {@code
* function (doc) {
* if (doc.location &&
@ -30,8 +24,9 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution
* }
* }}
*
* 2.4- MapReduce Views: Add new views in document 'campus':
* 2.4.1- view 'all' with function:
* 2.2- MapReduce Views: Add new views in document 'campus':
*
* 2.2.1- view 'all' with function:
* {@code
* function (doc, meta) {
* if(doc._class == "com.baeldung.spring.data.couchbase.model.Campus") {
@ -39,7 +34,7 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution
* }
* }}
*
* 2.4.2- view 'byName' with function:
* 2.2.2- view 'byName' with function:
* {@code
* function (doc, meta) {
* if(doc._class == "com.baeldung.spring.data.couchbase.model.Campus" &&

View File

@ -1,26 +0,0 @@
package com.baeldung.spring.data.couchbase;
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
public class CustomTypeKeyCouchbaseConfig extends MyCouchbaseConfig {
@Override
public String getConnectionString() {
return NODE_LIST;
}
@Override
public String getUserName() {
return BUCKET_USERNAME;
}
@Override
public String getPassword() {
return BUCKET_PASSWORD;
}
@Override
public String typeKey() {
return MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE;
}
}

View File

@ -1,11 +0,0 @@
package com.baeldung.spring.data.couchbase;
import com.couchbase.client.java.query.QueryScanConsistency;
public class ReadYourOwnWritesCouchbaseConfig extends MyCouchbaseConfig {
@Override
public QueryScanConsistency getDefaultConsistency() {
return QueryScanConsistency.REQUEST_PLUS;
}
}

View File

@ -7,4 +7,5 @@ This module contains articles about Spring aspect oriented programming (AOP)
- [Spring Performance Logging](https://www.baeldung.com/spring-performance-logging)
- [When Does Java Throw UndeclaredThrowableException?](https://www.baeldung.com/java-undeclaredthrowableexception)
- [Get Advised Method Info in Spring AOP](https://www.baeldung.com/spring-aop-get-advised-method-info)
- More articles: [[<-- prev]](/spring-aop)
- [Invoke Spring @Cacheable from Another Method of Same Bean](https://www.baeldung.com/spring-invoke-cacheable-other-method-same-bean)
- More articles: [[<-- prev]](/spring-aop)

View File

@ -0,0 +1,13 @@
package com.baeldung.permitallanonymous;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan("com.baeldung.permitallanonymous.*")
public class SecuredEcommerceApplication {
public static void main(String[] args) {
SpringApplication.run(SecuredEcommerceApplication.class, args);
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.permitallanonymous.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EcommerceController {
//can be accessed by only logged-in users
@GetMapping("/private/showCart")
public @ResponseBody String showCart() {
return "Show Cart";
}
//can we accessed by both anonymous and authenticated users
@GetMapping("/public/showProducts")
public @ResponseBody String listProducts() {
return "List Products";
}
//can be access by only anonymous users not by authenticated users
@GetMapping("/public/registerUser")
public @ResponseBody String registerUser() {
return "Register User";
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.permitallanonymous.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AuditInterceptor extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(AuditInterceptor.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof AnonymousAuthenticationToken) {
logger.info("Audit anonymous user");
}
if (authentication instanceof UsernamePasswordAuthenticationToken) {
logger.info("Audit registered user");
}
filterChain.doFilter(request, response);
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.permitallanonymous.security;
import com.baeldung.permitallanonymous.filter.AuditInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class EcommerceWebSecurityConfig {
@Bean
public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.withUsername("spring")
.password(passwordEncoder.encode("secret"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterAfter(new AuditInterceptor(), AnonymousAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/private/**").authenticated().and().httpBasic()
.and().authorizeRequests()
.antMatchers("/public/showProducts").permitAll()
.antMatchers("/public/registerUser").anonymous();
return http.build();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -0,0 +1,70 @@
package com.baeldung.permitallanonymous;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SecuredEcommerceApplication.class)
@AutoConfigureMockMvc
public class SecureEcommerceApplicationUnitTest {
@Autowired
private MockMvc mockMvc;
private static final Logger logger = LoggerFactory.getLogger(SecureEcommerceApplicationUnitTest.class);
@WithAnonymousUser
@Test
public void givenAnonymousUser_whenAccessToUserRegisterPage_thenAllowAccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/public/registerUser"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("Register User"));
}
@WithMockUser(username = "spring", password = "secret")
@Test
public void givenAuthenticatedUser_whenAccessToUserRegisterPage_thenDenyAccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/public/registerUser"))
.andExpect(MockMvcResultMatchers.status().isForbidden());
}
@WithMockUser(username = "spring", password = "secret")
@Test
public void givenAuthenticatedUser_whenAccessToProductLinePage_thenAllowAccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/public/showProducts"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("List Products"));
}
@WithAnonymousUser
@Test
public void givenAnonymousUser_whenAccessToProductLinePage_thenAllowAccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/public/showProducts"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("List Products"));
}
@WithMockUser(username = "spring", password = "secret")
@Test
public void givenAuthenticatedUser_whenAccessToCartPage_thenAllowAccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/private/showCart"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("Show Cart"));
}
@WithAnonymousUser
@Test
public void givenAnonymousUser_whenAccessToCartPage_thenDenyAccess() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/private/showCart"))
.andExpect(MockMvcResultMatchers.status().isUnauthorized());
}
}

View File

@ -1 +1,2 @@
## Relevant Articles
- [Securing Spring Boot 3 Applications With SSL Bundles](https://www.baeldung.com/spring-boot-security-ssl-bundles)

View File

@ -5,3 +5,4 @@ This module contains articles about Spring Vault
### Relevant Articles:
- [Spring Vault](https://www.baeldung.com/spring-vault)
- [Secure Kubernetes Secrets with Vault](https://www.baeldung.com/spring-vault-kubernetes-secrets)

View File

@ -1,2 +1,2 @@
### Relevant Articles:
- [Test Main Method with JUnit](http://www.baeldung.com/junit-5)
- [Test Main Method with JUnit](https://www.baeldung.com/junit-test-main-method)

View File

@ -7,3 +7,4 @@ This module contains articles about Mockito
- [Resolving Mockito Exception: Wanted But Not Invoked](https://www.baeldung.com/mockito-exception-wanted-but-not-invoked)
- [Matching Null With Mockito](https://www.baeldung.com/mockito-match-null)
- [Mock Same Method with Different Parameters](https://www.baeldung.com/java-mock-same-method-other-parameters)
- [How to Mock Constructors for Unit Testing using Mockito](https://www.baeldung.com/java-mockito-constructors-unit-testing)

View File

@ -5,3 +5,4 @@
- [Assert That a Java Optional Has a Certain Value](https://www.baeldung.com/java-optional-assert-value)
- [Assert That an Object Is From a Specific Type](https://www.baeldung.com/java-assert-object-of-type)
- [Asserting Equality on Two Classes Without an equals() Method](https://www.baeldung.com/java-assert-equality-no-equals)
- [Assert Regex Matches in JUnit](https://www.baeldung.com/junit-assert-regex-matches)