diff --git a/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java new file mode 100644 index 0000000000..33243c4ecf --- /dev/null +++ b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/record/Person.java @@ -0,0 +1,22 @@ +package com.baeldung.java14.record; + +import java.util.Objects; + +public record Person (String name, String address) { + + public static String UNKWOWN_ADDRESS = "Unknown"; + public static String UNNAMED = "Unnamed"; + + public Person { + Objects.requireNonNull(name); + Objects.requireNonNull(address); + } + + public Person(String name) { + this(name, UNKWOWN_ADDRESS); + } + + public static Person unnamed(String address) { + return new Person(UNNAMED, address); + } +} diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/foreign/api/ForeignMemoryUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/foreign/api/ForeignMemoryUnitTest.java new file mode 100644 index 0000000000..b2264f30e6 --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/foreign/api/ForeignMemoryUnitTest.java @@ -0,0 +1,84 @@ +package com.baeldung.java14.foreign.api; + +import jdk.incubator.foreign.*; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; + +public class ForeignMemoryUnitTest { + + @Test + public void whenAValueIsSet_thenAccessTheValue() { + long value = 10; + MemoryAddress memoryAddress = + MemorySegment.allocateNative(8).baseAddress(); + VarHandle varHandle = MemoryHandles.varHandle(long.class, + ByteOrder.nativeOrder()); + varHandle.set(memoryAddress, value); + assertThat(varHandle.get(memoryAddress), is(value)); + } + + @Test + public void whenMultipleValuesAreSet_thenAccessAll() { + VarHandle varHandle = MemoryHandles.varHandle(int.class, + ByteOrder.nativeOrder()); + + try(MemorySegment memorySegment = + MemorySegment.allocateNative(100)) { + MemoryAddress base = memorySegment.baseAddress(); + for(int i=0; i<25; i++) { + varHandle.set(base.addOffset((i*4)), i); + } + for(int i=0; i<25; i++) { + assertThat(varHandle.get(base.addOffset((i*4))), is(i)); + } + } + } + + @Test + public void whenSetValuesWithMemoryLayout_thenTheyCanBeRetrieved() { + SequenceLayout sequenceLayout = + MemoryLayout.ofSequence(25, + MemoryLayout.ofValueBits(64, ByteOrder.nativeOrder())); + VarHandle varHandle = + sequenceLayout.varHandle(long.class, + MemoryLayout.PathElement.sequenceElement()); + + try(MemorySegment memorySegment = + MemorySegment.allocateNative(sequenceLayout)) { + MemoryAddress base = memorySegment.baseAddress(); + for(long i=0; i convertListAfterJava8(List list) { - Map map = list.stream().collect(Collectors.toMap(Animal::getId, animal -> animal)); + Map map = list.stream().collect(Collectors.toMap(Animal::getId, Function.identity())); return map; } diff --git a/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/CollectionToArrayListUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/CollectionToArrayListUnitTest.java index ad2ab2a756..15960c300d 100644 --- a/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/CollectionToArrayListUnitTest.java +++ b/java-collections-conversions/src/test/java/com/baeldung/convertcollectiontoarraylist/CollectionToArrayListUnitTest.java @@ -53,14 +53,14 @@ public class CollectionToArrayListUnitTest { verifyShallowCopy(srcCollection, newList); } - + /** * Section 5. Deep Copy */ @Test public void whenUsingDeepCopy_thenVerifyDeepCopy() { ArrayList newList = srcCollection.stream() - .map(foo -> foo.deepCopy()) + .map(Foo::deepCopy) .collect(toCollection(ArrayList::new)); verifyDeepCopy(srcCollection, newList); @@ -83,13 +83,13 @@ public class CollectionToArrayListUnitTest { * @param a * @param b */ - private void verifyShallowCopy(Collection a, Collection b) { + private void verifyShallowCopy(Collection a, Collection b) { assertEquals("Collections have different lengths", a.size(), b.size()); Iterator iterA = a.iterator(); Iterator iterB = b.iterator(); while (iterA.hasNext()) { // use '==' to test instance identity - assertTrue("Foo instances differ!", iterA.next() == iterB.next()); + assertSame("Foo instances differ!", iterA.next(), iterB.next()); } } @@ -98,7 +98,7 @@ public class CollectionToArrayListUnitTest { * @param a * @param b */ - private void verifyDeepCopy(Collection a, Collection b) { + private void verifyDeepCopy(Collection a, Collection b) { assertEquals("Collections have different lengths", a.size(), b.size()); Iterator iterA = a.iterator(); Iterator iterB = b.iterator(); @@ -106,7 +106,7 @@ public class CollectionToArrayListUnitTest { Foo nextA = iterA.next(); Foo nextB = iterB.next(); // should not be same instance - assertFalse("Foo instances are the same!", nextA == nextB); + assertNotSame("Foo instances are the same!", nextA, nextB); // but should have same content assertFalse("Foo instances have different content!", fooDiff(nextA, nextB)); } diff --git a/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java index 4d6cba7d27..7d94f88d21 100644 --- a/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java +++ b/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java @@ -23,7 +23,7 @@ public class ConvertIteratorToListServiceUnitTest { Iterator iterator; @Before - public void setUp() throws Exception { + public void setUp() { iterator = Arrays.asList(1, 2, 3) .iterator(); } @@ -31,7 +31,7 @@ public class ConvertIteratorToListServiceUnitTest { @Test public void givenAnIterator_whenConvertIteratorToListUsingWhileLoop_thenReturnAList() { - List actualList = new ArrayList(); + List actualList = new ArrayList<>(); // Convert Iterator to List using while loop dsf while (iterator.hasNext()) { @@ -44,7 +44,7 @@ public class ConvertIteratorToListServiceUnitTest { @Test public void givenAnIterator_whenConvertIteratorToListAfterJava8_thenReturnAList() { - List actualList = new ArrayList(); + List actualList = new ArrayList<>(); // Convert Iterator to List using Java 8 iterator.forEachRemaining(actualList::add); diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/DockerPatternConverter.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/DockerPatternConverter.java new file mode 100644 index 0000000000..c2e40cd565 --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/DockerPatternConverter.java @@ -0,0 +1,30 @@ +package com.baeldung.logging.log4j2.plugins; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.pattern.ConverterKeys; +import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; +import org.apache.logging.log4j.core.pattern.PatternConverter; + +@Plugin(name = "DockerPatternConverter", category = PatternConverter.CATEGORY) +@ConverterKeys({"docker", "container"}) +public class DockerPatternConverter extends LogEventPatternConverter { + + private DockerPatternConverter(String[] options) { + super("Docker", "docker"); + } + + public static DockerPatternConverter newInstance(String[] options) { + return new DockerPatternConverter(options); + } + + @Override + public void format(LogEvent event, StringBuilder toAppendTo) { + toAppendTo.append(dockerContainer()); + } + + private String dockerContainer() { + //get docker container ID inside which application is running here + return "container-1"; + } +} diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaAppender.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaAppender.java new file mode 100644 index 0000000000..3e91aa5e94 --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaAppender.java @@ -0,0 +1,133 @@ +package com.baeldung.logging.log4j2.plugins; + +import org.apache.logging.log4j.core.Core; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required; + +import java.io.Serializable; + +@Plugin(name = "Kafka2", category = Core.CATEGORY_NAME) +public class KafkaAppender extends AbstractAppender { + + @PluginBuilderFactory + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder implements org.apache.logging.log4j.core.util.Builder { + + @PluginBuilderAttribute("name") + @Required + private String name; + + @PluginBuilderAttribute("ip") + private String ipAddress; + + @PluginBuilderAttribute("port") + private int port; + + @PluginBuilderAttribute("topic") + private String topic; + + @PluginBuilderAttribute("partition") + private String partition; + + @PluginElement("Layout") + private Layout layout; + + @PluginElement("Filter") + private Filter filter; + + public Layout getLayout() { + return layout; + } + + public Builder setLayout(Layout layout) { + this.layout = layout; + return this; + } + + public Filter getFilter() { + return filter; + } + + public String getName() { + return name; + } + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setFilter(Filter filter) { + this.filter = filter; + return this; + } + + public String getIpAddress() { + return ipAddress; + } + + public Builder setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + return this; + } + + public int getPort() { + return port; + } + + public Builder setPort(int port) { + this.port = port; + return this; + } + + public String getTopic() { + return topic; + } + + public Builder setTopic(String topic) { + this.topic = topic; + return this; + } + + public String getPartition() { + return partition; + } + + public Builder setPartition(String partition) { + this.partition = partition; + return this; + } + + @Override + public KafkaAppender build() { + return new KafkaAppender(getName(), getFilter(), getLayout(), true, new KafkaBroker(ipAddress, port, topic, partition)); + } + } + + private KafkaBroker broker; + + private KafkaAppender(String name, Filter filter, Layout layout, boolean ignoreExceptions, KafkaBroker broker) { + super(name, filter, layout, ignoreExceptions); + this.broker = broker; + } + + @Override + public void append(LogEvent event) { + + connectAndSendToKafka(broker, event); + } + + private void connectAndSendToKafka(KafkaBroker broker, LogEvent event) { + //send to Kafka + } +} diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaBroker.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaBroker.java new file mode 100644 index 0000000000..0479e71c41 --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaBroker.java @@ -0,0 +1,38 @@ +package com.baeldung.logging.log4j2.plugins; + +import java.io.Serializable; + +public class KafkaBroker implements Serializable { + + private final String ipAddress; + private final int port; + + public KafkaBroker(String ipAddress, int port, String topic, String partition) { + this.ipAddress = ipAddress; + this.port = port; + this.topic = topic; + this.partition = partition; + } + + public String getTopic() { + return topic; + } + + public String getPartition() { + return partition; + } + + private final String topic; + private final String partition; + + + public String getIpAddress() { + return ipAddress; + } + + public int getPort() { + return port; + } + + +} diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaLookup.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaLookup.java new file mode 100644 index 0000000000..c2679861c4 --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/KafkaLookup.java @@ -0,0 +1,24 @@ +package com.baeldung.logging.log4j2.plugins; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.lookup.StrLookup; + +@Plugin(name = "kafka", category = StrLookup.CATEGORY) +public class KafkaLookup implements StrLookup { + + @Override + public String lookup(String key) { + return getFromKafka(key); + } + + @Override + public String lookup(LogEvent event, String key) { + return getFromKafka(key); + } + + private String getFromKafka(String topicName) { + //kafka search logic should go here + return "topic1-p1"; + } +} diff --git a/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/ListAppender.java b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/ListAppender.java new file mode 100644 index 0000000000..e3819028db --- /dev/null +++ b/logging-modules/log4j2/src/main/java/com/baeldung/logging/log4j2/plugins/ListAppender.java @@ -0,0 +1,48 @@ +/** + * + */ +package com.baeldung.logging.log4j2.plugins; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Core; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static java.util.Collections.synchronizedList; + +@Plugin(name = "ListAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) +public class ListAppender extends AbstractAppender { + + private List logList; + + protected ListAppender(String name, Filter filter) { + super(name, filter, null); + logList = synchronizedList(new ArrayList<>()); + } + + @PluginFactory + public static ListAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filter") final Filter filter) { + return new ListAppender(name, filter); + } + + @Override + public void append(LogEvent event) { + if (event.getLevel() + .isLessSpecificThan(Level.WARN)) { + error("Unable to log less than WARN level."); + return; + } + logList.add(event); + } + +} diff --git a/logging-modules/log4j2/src/test/resources/log4j2.xml b/logging-modules/log4j2/src/test/resources/log4j2.xml index ee26bcecf2..050e0aa705 100644 --- a/logging-modules/log4j2/src/test/resources/log4j2.xml +++ b/logging-modules/log4j2/src/test/resources/log4j2.xml @@ -50,6 +50,12 @@ + + + + + + + + + diff --git a/spring-session/pom.xml b/spring-session/pom.xml index 42a414afdc..8388efb6c3 100644 --- a/spring-session/pom.xml +++ b/spring-session/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 diff --git a/spring-session/spring-session-redis/pom.xml b/spring-session/spring-session-redis/pom.xml index 37402634b0..8d225e06ed 100644 --- a/spring-session/spring-session-redis/pom.xml +++ b/spring-session/spring-session-redis/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../parent-boot-2 @@ -25,7 +25,7 @@ org.springframework.session - spring-session + spring-session-data-redis org.springframework.boot @@ -36,6 +36,11 @@ embedded-redis ${embedded-redis.version} + + redis.clients + jedis + jar + diff --git a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java b/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java index 1da6d9422d..678c98e7eb 100644 --- a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java +++ b/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java @@ -1,23 +1,31 @@ package com.baeldung.spring.session; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { - + @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("admin").password("password").roles("ADMIN"); + auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("password")).roles("ADMIN"); } - + @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic().and().authorizeRequests().antMatchers("/").hasRole("ADMIN").anyRequest().authenticated(); } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } } diff --git a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java b/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java index 7ee0294315..065533c73f 100644 --- a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java +++ b/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java @@ -5,7 +5,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml index 9fa839f1c2..628f439cc0 100644 --- a/spring-social-login/pom.xml +++ b/spring-social-login/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -42,15 +42,16 @@ org.thymeleaf.extras - thymeleaf-extras-springsecurity4 + thymeleaf-extras-springsecurity5 org.springframework.social spring-social-facebook + ${spring.social.facebook.version} - + org.springframework.boot spring-boot-starter-data-jpa @@ -60,6 +61,12 @@ com.h2database h2 + + + net.bytebuddy + byte-buddy-dep + ${bytebuddy.version} + @@ -93,5 +100,10 @@ + + + 1.10.9 + 2.0.3.RELEASE + \ No newline at end of file diff --git a/spring-social-login/src/main/java/com/baeldung/config/Application.java b/spring-social-login/src/main/java/com/baeldung/config/Application.java index 5d083d2d47..c65df6dbfe 100644 --- a/spring-social-login/src/main/java/com/baeldung/config/Application.java +++ b/spring-social-login/src/main/java/com/baeldung/config/Application.java @@ -3,7 +3,7 @@ package com.baeldung.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication diff --git a/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java b/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java index 3d3081fef9..152c7b229a 100644 --- a/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java +++ b/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java @@ -1,8 +1,7 @@ package com.baeldung.config; -import com.baeldung.security.FacebookSignInAdapter; -import com.baeldung.security.FacebookConnectionSignup; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -14,22 +13,27 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.social.connect.ConnectionFactoryLocator; import org.springframework.social.connect.UsersConnectionRepository; import org.springframework.social.connect.mem.InMemoryUsersConnectionRepository; +import org.springframework.social.connect.support.ConnectionFactoryRegistry; import org.springframework.social.connect.web.ProviderSignInController; +import org.springframework.social.facebook.connect.FacebookConnectionFactory; + +import com.baeldung.security.FacebookConnectionSignup; +import com.baeldung.security.FacebookSignInAdapter; @Configuration @EnableWebSecurity @ComponentScan(basePackages = { "com.baeldung.security" }) public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("${spring.social.facebook.appSecret}") + String appSecret; + + @Value("${spring.social.facebook.appId}") + String appId; @Autowired private UserDetailsService userDetailsService; - @Autowired - private ConnectionFactoryLocator connectionFactoryLocator; - - @Autowired - private UsersConnectionRepository usersConnectionRepository; - @Autowired private FacebookConnectionSignup facebookConnectionSignup; @@ -55,7 +59,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean // @Primary public ProviderSignInController providerSignInController() { + ConnectionFactoryLocator connectionFactoryLocator = connectionFactoryLocator(); + UsersConnectionRepository usersConnectionRepository = getUsersConnectionRepository(connectionFactoryLocator); ((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup); return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new FacebookSignInAdapter()); } + + private ConnectionFactoryLocator connectionFactoryLocator() { + ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry(); + registry.addConnectionFactory(new FacebookConnectionFactory(appId, appSecret)); + return registry; + } + + private UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) { + return new InMemoryUsersConnectionRepository(connectionFactoryLocator); + } } \ No newline at end of file