From 7723b1be724310262f700a450df2da10e2bc0ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jare=C5=A1?= Date: Tue, 26 Sep 2023 14:28:04 +0200 Subject: [PATCH 1/3] update EhCache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pavel Jareš --- .../java/org/zowe/apiml/util/CacheUtils.java | 36 +++--- .../org/zowe/apiml/util/CacheUtilsTest.java | 101 +++++++-------- config/local-multi/gateway-service-1.yml | 3 - config/local-multi/gateway-service-2.yml | 3 - config/local/gateway-service.yml | 3 - .../apiml/gateway/config/CacheConfig.java | 22 ++-- .../ServiceAuthenticationServiceImpl.java | 28 +++-- .../src/main/resources/application.yml | 3 - .../src/main/resources/ehcache.xml | 116 +++++++++++++++--- .../security/MockedSecurityContext.java | 4 +- .../ServiceAuthenticationServiceImplTest.java | 28 +++-- .../src/test/resources/application-test.yml | 3 - .../src/test/resources/application.yml | 3 - gradle/versions.gradle | 4 +- 14 files changed, 214 insertions(+), 143 deletions(-) diff --git a/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java b/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java index 82bba061db..82222aae48 100644 --- a/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java +++ b/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java @@ -10,14 +10,16 @@ package org.zowe.apiml.util; -import net.sf.ehcache.Element; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.zowe.apiml.cache.CompositeKey; import java.util.List; +import java.util.Set; +import java.util.Spliterator; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.StreamSupport; /** * This utils offer base operation with cache, which can be shared to multiple codes. @@ -61,18 +63,15 @@ public void evictSubset(CacheManager cacheManager, String cacheName, Predicate> spliterator = ((javax.cache.Cache) nativeCache).spliterator(); + Set keysToRemove = StreamSupport.stream(spliterator, true) + // if entry is compositeKey and first param is the same filter it to be removed or + // if key is not composite key (unknown for evict) evict record (as failover) + .filter(e -> !(e.getKey() instanceof CompositeKey) || keyPredicate.test((CompositeKey) e.getKey())) + .map(javax.cache.Cache.Entry::getKey) + .collect(Collectors.toSet()); + ((javax.cache.Cache) nativeCache).removeAll(keysToRemove); } else { // in case of using different cache manager, evict all records for sure cache.clear(); @@ -93,14 +92,9 @@ public List getAllRecords(CacheManager cacheManager, String cacheName) { if (cache == null) throw new IllegalArgumentException("Unknown cache " + cacheName); final Object nativeCache = cache.getNativeCache(); - if (nativeCache instanceof net.sf.ehcache.Cache) { - final net.sf.ehcache.Cache ehCache = (net.sf.ehcache.Cache) nativeCache; - - return (List) ehCache.getAll(ehCache.getKeys()) - .values() - .stream() - .map(Element::getObjectValue) - .collect(Collectors.toList()); + if (nativeCache instanceof javax.cache.Cache) { + Spliterator> spliterator = ((javax.cache.Cache) nativeCache).spliterator(); + return StreamSupport.stream(spliterator, true).map(javax.cache.Cache.Entry::getValue).collect(Collectors.toList()); } else { throw new IllegalArgumentException("Unsupported type of cache : " + nativeCache.getClass()); } diff --git a/common-service-core/src/test/java/org/zowe/apiml/util/CacheUtilsTest.java b/common-service-core/src/test/java/org/zowe/apiml/util/CacheUtilsTest.java index c70813bd07..8cb40c3bd1 100644 --- a/common-service-core/src/test/java/org/zowe/apiml/util/CacheUtilsTest.java +++ b/common-service-core/src/test/java/org/zowe/apiml/util/CacheUtilsTest.java @@ -10,34 +10,16 @@ package org.zowe.apiml.util; -import net.sf.ehcache.Element; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.stubbing.Answer; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.zowe.apiml.cache.CompositeKey; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; class CacheUtilsTest { @@ -49,6 +31,25 @@ void setUp() { underTest = new CacheUtils(); } + private javax.cache.Cache.Entry createEntry(Object key, Object value) { + return new javax.cache.Cache.Entry() { + @Override + public Object getKey() { + return key; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public T unwrap(Class clazz) { + return (T) value; + } + }; + } + @Test void testEvictSubset() { CacheManager cacheManager = mock(CacheManager.class); @@ -60,7 +61,7 @@ void testEvictSubset() { Cache cache2 = mock(Cache.class); when(cacheManager.getCache("cache2")).thenReturn(cache2); - net.sf.ehcache.Cache ehCache2 = mock(net.sf.ehcache.Cache.class); + javax.cache.Cache ehCache2 = mock(javax.cache.Cache.class); when(cache2.getNativeCache()).thenReturn(ehCache2); List keys = Arrays.asList( @@ -69,7 +70,14 @@ void testEvictSubset() { new CompositeKey("next", 10), new CompositeKey("next", 15) ); - when(ehCache2.getKeys()).thenReturn(keys); + List> values = Arrays.asList( + createEntry(keys.get(0), "A"), + createEntry(keys.get(1), "B"), + createEntry(keys.get(2), "C"), + createEntry(keys.get(3), "D") + ); + + when(ehCache2.spliterator()).thenAnswer(invocation -> values.spliterator()); try { underTest.evictSubset(cacheManager, "missing", x -> true); @@ -79,34 +87,20 @@ void testEvictSubset() { assertTrue(e.getMessage().contains("missing")); } - // not EhCache - clean all, dont use keyPredicate + // not EhCache - clean all, do not use keyPredicate verify(cache1, never()).clear(); underTest.evictSubset(cacheManager, "cache1", x -> false); verify(cache1, times(1)).clear(); - final Answer answer = invocation -> { - removeCounter++; - return true; - }; - - doAnswer(answer).when(ehCache2).remove(any(Serializable.class)); - doAnswer(answer).when(ehCache2).remove((Object) any()); - - assertEquals(0, removeCounter); // in all cases remove entries without CompositeKey underTest.evictSubset(cacheManager, "cache2", x -> false); - assertEquals(1, removeCounter); - verify(ehCache2, times(1)).remove(keys.get(0)); + verify(ehCache2, times(1)).removeAll(Collections.singleton(keys.get(0))); underTest.evictSubset(cacheManager, "cache2", x -> x.equals(0, "test")); - assertEquals(3, removeCounter); - verify(ehCache2, times(2)).remove(keys.get(0)); - verify(ehCache2, times(1)).remove(keys.get(1)); + verify(ehCache2, times(1)).removeAll(new HashSet(Arrays.asList(keys.get(0), keys.get(1)))); underTest.evictSubset(cacheManager, "cache2", x -> (Integer) x.get(1) > 10); - assertEquals(5, removeCounter); - verify(ehCache2, times(3)).remove(keys.get(0)); - verify(ehCache2, times(1)).remove(keys.get(3)); + verify(ehCache2, times(1)).removeAll(new HashSet(Arrays.asList(keys.get(0), keys.get(3)))); } @Test @@ -132,30 +126,21 @@ void givenUnsupportedCacheManager_whenGetAllRecords_thenThrowsException() { assertTrue(iae.getMessage().startsWith("Unsupported type of cache : ")); } - private Map convert(Map in) { - Map out = new HashMap<>(); - for (Map.Entry entry : in.entrySet()) { - out.put(entry.getKey(), new Element(entry.getKey(), entry.getValue())); - } - return out; - } - @Test void givenValidCacheManager_whenGetAllRecords_thenReadAllStoredRecords() { CacheManager cacheManager = mock(CacheManager.class); Cache cache = mock(Cache.class); - net.sf.ehcache.Cache ehCache = mock(net.sf.ehcache.Cache.class); + javax.cache.Cache ehCache = mock(javax.cache.Cache.class); - Map entries = new HashMap<>(); - entries.put(1, "a"); - entries.put(2, "b"); - entries.put(3, "c"); - List keys = new ArrayList<>(entries.keySet()); + List entries = Arrays.asList( + createEntry(1, "a"), + createEntry(2, "b"), + createEntry(3, "c") + ); when(cacheManager.getCache("knownCacheName")).thenReturn(cache); when(cache.getNativeCache()).thenReturn(ehCache); - when(ehCache.getKeys()).thenReturn(keys); - when(ehCache.getAll(keys)).thenReturn(convert(entries)); + when(ehCache.spliterator()).thenAnswer(invocation -> entries.spliterator()); Collection values = underTest.getAllRecords(cacheManager, "knownCacheName"); assertNotNull(values); diff --git a/config/local-multi/gateway-service-1.yml b/config/local-multi/gateway-service-1.yml index ad9810f814..990960c756 100644 --- a/config/local-multi/gateway-service-1.yml +++ b/config/local-multi/gateway-service-1.yml @@ -28,9 +28,6 @@ spring: output: ansi: enabled: always - cache: - ehcache: - config: classpath:ehcache.xml server: internal: diff --git a/config/local-multi/gateway-service-2.yml b/config/local-multi/gateway-service-2.yml index 379a518aea..f8edeb3c0f 100644 --- a/config/local-multi/gateway-service-2.yml +++ b/config/local-multi/gateway-service-2.yml @@ -28,9 +28,6 @@ spring: output: ansi: enabled: always - cache: - ehcache: - config: classpath:ehcache.xml server: internal: diff --git a/config/local/gateway-service.yml b/config/local/gateway-service.yml index 12b54c1cb5..e2c4348c08 100644 --- a/config/local/gateway-service.yml +++ b/config/local/gateway-service.yml @@ -46,9 +46,6 @@ spring: output: ansi: enabled: always - cache: - ehcache: - config: classpath:ehcache.xml server: internal: diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/CacheConfig.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/CacheConfig.java index f7236af537..1d4be63428 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/CacheConfig.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/CacheConfig.java @@ -12,9 +12,9 @@ import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.cache.ehcache.EhCacheCacheManager; -import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.cache.jcache.JCacheCacheManager; +import org.springframework.cache.jcache.JCacheManagerFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -23,6 +23,7 @@ import org.zowe.apiml.util.CacheUtils; import javax.annotation.PostConstruct; +import java.io.IOException; /** * Spring configuration to use EhCache. This context is using from application and also from tests. @@ -48,18 +49,17 @@ public void afterPropertiesSet() { } @Bean - public CacheManager cacheManager() { - net.sf.ehcache.CacheManager cache = ehCacheCacheManager().getObject(); - assert cache != null; - return new EhCacheCacheManager(cache); + public JCacheManagerFactoryBean cacheManagerFactoryBean() throws IOException { + JCacheManagerFactoryBean jCacheManagerFactoryBean = new JCacheManagerFactoryBean(); + jCacheManagerFactoryBean.setCacheManagerUri(new ClassPathResource("ehcache.xml").getURI()); + return jCacheManagerFactoryBean; } @Bean - public EhCacheManagerFactoryBean ehCacheCacheManager() { - EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean(); - cmfb.setConfigLocation(new ClassPathResource("ehcache.xml")); - cmfb.setShared(true); - return cmfb; + public CacheManager cacheManager() throws IOException { + final JCacheCacheManager jCacheCacheManager = new JCacheCacheManager(); + jCacheCacheManager.setCacheManager(cacheManagerFactoryBean().getObject()); + return jCacheCacheManager; } @Bean(CacheConfig.COMPOSITE_KEY_GENERATOR) diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java index 3a5b6ea1c0..139bb1bf6e 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java @@ -13,11 +13,12 @@ import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClient; import com.netflix.discovery.shared.Application; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.apache.commons.lang.StringUtils; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.zowe.apiml.auth.Authentication; import org.zowe.apiml.eurekaservice.client.util.EurekaMetadataParser; @@ -30,18 +31,19 @@ import org.zowe.apiml.gateway.security.service.schema.source.AuthSource; import org.zowe.apiml.util.CacheUtils; +import javax.annotation.PostConstruct; import java.util.List; import java.util.Optional; /** - * This bean is responsible for "translating" security to specific service. It decorate request with security data for + * This bean is responsible for "translating" security to specific service. It decorates request with security data for * specific service. Implementation of security updates are defined with beans extending * {@link IAuthenticationScheme}. *

* The main idea of this bean is to create command * {@link AuthenticationCommand}. Command is object which update the * request for specific scheme (defined by service). This bean is responsible for getting the right command. If it is - * possible to decide now for just one scheme type, bean return this command to update request immediatelly. + * possible to decide now for just one scheme type, bean return this command to update request immediately. * This command write in the ZUUL context * UniversalAuthenticationCommand, which is used in Ribbon loadbalancer. There is a listener which work with this value. * After load balancer will decide which instance will be used, universal command is called and update the request. @@ -54,18 +56,27 @@ * also in loadbalancer */ @Service -@AllArgsConstructor +@RequiredArgsConstructor public class ServiceAuthenticationServiceImpl implements ServiceAuthenticationService { private static final String CACHE_BY_SERVICE_ID = "serviceAuthenticationByServiceId"; - private static final String CACHE_BY_AUTHENTICATION = "serviceAuthenticationByAuthentication"; + static final String CACHE_BY_AUTHENTICATION = "serviceAuthenticationByAuthentication"; + private final ApplicationContext applicationContext; private final EurekaClient discoveryClient; private final EurekaMetadataParser eurekaMetadataParser; private final AuthenticationSchemeFactory authenticationSchemeFactory; private final CacheManager cacheManager; private final CacheUtils cacheUtils; + // to force calling inside methods with aspects - ie. ehCache aspect + private ServiceAuthenticationService meAsProxy; + + @PostConstruct + public void afterPropertiesSet() { + meAsProxy = applicationContext.getBean(ServiceAuthenticationService.class); + } + public Authentication getAuthentication(InstanceInfo instanceInfo) { return eurekaMetadataParser.parseAuthentication(instanceInfo.getMetadata()); } @@ -90,8 +101,9 @@ public Authentication getAuthentication(String serviceId) { } @Override + @RetryIfExpired @CacheEvict(value = CACHE_BY_AUTHENTICATION, condition = "#result != null && #result.isExpired()") - @Cacheable(CACHE_BY_AUTHENTICATION) + @Cacheable(value = CACHE_BY_AUTHENTICATION, unless = "#result == null") public AuthenticationCommand getAuthenticationCommand(Authentication authentication, AuthSource authSource) { final IAuthenticationScheme scheme = authenticationSchemeFactory.getSchema(authentication.getScheme()); return scheme.createCommand(authentication, authSource); @@ -104,12 +116,12 @@ public AuthenticationCommand getAuthenticationCommand(Authentication authenticat condition = "#result != null && #result.isExpired()", keyGenerator = CacheConfig.COMPOSITE_KEY_GENERATOR ) - @Cacheable(value = CACHE_BY_SERVICE_ID, keyGenerator = CacheConfig.COMPOSITE_KEY_GENERATOR) + @Cacheable(value = CACHE_BY_SERVICE_ID, keyGenerator = CacheConfig.COMPOSITE_KEY_GENERATOR, unless = "#result == null") public AuthenticationCommand getAuthenticationCommand(String serviceId, Authentication found, AuthSource authSource) { // if no instance exist or no metadata found, do nothing if (found == null || found.isEmpty()) return AuthenticationCommand.EMPTY; - return getAuthenticationCommand(found, authSource); + return meAsProxy.getAuthenticationCommand(found, authSource); } public Optional getAuthSourceByAuthentication(Authentication authentication) { diff --git a/gateway-service/src/main/resources/application.yml b/gateway-service/src/main/resources/application.yml index a2b2e7f4b3..9b20ea2dd9 100644 --- a/gateway-service/src/main/resources/application.yml +++ b/gateway-service/src/main/resources/application.yml @@ -118,9 +118,6 @@ spring: output: ansi: enabled: detect - cache: - ehcache: - config: classpath:ehcache.xml main: banner-mode: ${apiml.banner:"off"} allow-circular-references: true diff --git a/gateway-service/src/main/resources/ehcache.xml b/gateway-service/src/main/resources/ehcache.xml index 19dceab253..e7d2c3241e 100644 --- a/gateway-service/src/main/resources/ehcache.xml +++ b/gateway-service/src/main/resources/ehcache.xml @@ -1,20 +1,106 @@ - + - + - + + + - - - - - - - - - - - + + java.lang.String + java.lang.Boolean + + 1 + + + 1 + 10 + + - + + java.lang.String + org.zowe.apiml.security.common.token.TokenAuthentication + + 1 + + 1000 + + + + org.zowe.apiml.cache.CompositeKey + org.zowe.apiml.gateway.security.service.schema.AuthenticationCommand + + 1 + + 1000 + + + + org.springframework.cache.interceptor.SimpleKey + org.zowe.apiml.gateway.security.service.schema.AuthenticationCommand + + 1 + + 1000 + + + + java.lang.String + java.lang.String + + 1 + + 10 + + + + java.lang.String + java.lang.Boolean + + 1 + + 10 + + + + org.springframework.http.HttpHeaders + java.lang.Boolean + + 1 + + 10 + + + + org.zowe.apiml.gateway.security.service.schema.source.AuthSource + java.lang.Boolean + + 20 + + 1000 + + + + org.zowe.apiml.gateway.security.service.schema.source.AuthSource + org.zowe.apiml.gateway.security.service.schema.source.AuthSource.Parsed + + 20 + + 1000 + + + + java.lang.String + java.util.List + + 1 + + 1000 + + + \ No newline at end of file diff --git a/gateway-service/src/test/java/org/zowe/apiml/config/service/security/MockedSecurityContext.java b/gateway-service/src/test/java/org/zowe/apiml/config/service/security/MockedSecurityContext.java index 4ffebd7262..24bddb1e90 100644 --- a/gateway-service/src/test/java/org/zowe/apiml/config/service/security/MockedSecurityContext.java +++ b/gateway-service/src/test/java/org/zowe/apiml/config/service/security/MockedSecurityContext.java @@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.cache.CacheManager; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.zowe.apiml.eurekaservice.client.util.EurekaMetadataParser; import org.zowe.apiml.gateway.security.service.AuthenticationService; @@ -55,8 +56,9 @@ public AuthSourceService getAuthSourceService() { } @Bean - public ServiceAuthenticationService getServiceAuthenticationService(@Autowired CacheManager cacheManager, CacheUtils cacheUtils) { + public ServiceAuthenticationService getServiceAuthenticationService(ApplicationContext applicationContext, @Autowired CacheManager cacheManager, CacheUtils cacheUtils) { return new ServiceAuthenticationServiceImpl( + applicationContext, getDiscoveryClient(), getEurekaMetadataParser(), getAuthenticationSchemeFactory(), diff --git a/gateway-service/src/test/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImplTest.java b/gateway-service/src/test/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImplTest.java index 2f669c0ebb..78f7e4f876 100644 --- a/gateway-service/src/test/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImplTest.java +++ b/gateway-service/src/test/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImplTest.java @@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -59,6 +60,7 @@ import static org.mockito.Mockito.*; import static org.zowe.apiml.constants.EurekaMetadataDefinition.AUTHENTICATION_APPLID; import static org.zowe.apiml.constants.EurekaMetadataDefinition.AUTHENTICATION_SCHEME; +import static org.zowe.apiml.gateway.security.service.ServiceAuthenticationServiceImpl.CACHE_BY_AUTHENTICATION; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { @@ -69,6 +71,9 @@ @EnableAspectJAutoProxy class ServiceAuthenticationServiceImplTest extends CurrentRequestContextTest { + @Autowired + private ApplicationContext applicationContext; + @Autowired private EurekaClient discoveryClient; @@ -97,11 +102,13 @@ void init() { serviceAuthenticationService.evictCacheAllService(); serviceAuthenticationServiceImpl = new ServiceAuthenticationServiceImpl( + applicationContext, discoveryClient, new EurekaMetadataParser(), authenticationSchemeFactory, cacheManager, new CacheUtils()); + serviceAuthenticationServiceImpl.afterPropertiesSet(); } @AfterEach @@ -299,13 +306,13 @@ void testGetAuthenticationCommand(List authSourceList) { assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth1, authSource2)); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0002", auth1, authSource1)); - verify(baypassSchemeMock, times(2)).createCommand(auth1, authSource1); + verify(baypassSchemeMock, times(1)).createCommand(auth1, authSource1); verify(baypassSchemeMock, times(1)).createCommand(auth1, authSource2); serviceAuthenticationService.evictCacheService("service0001"); + cacheManager.getCache(CACHE_BY_AUTHENTICATION).clear(); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth1, authSource1)); - verify(baypassSchemeMock, times(3)).createCommand(auth1, authSource1); + verify(baypassSchemeMock, times(2)).createCommand(auth1, authSource1); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth1, authSource2)); verify(baypassSchemeMock, times(2)).createCommand(auth1, authSource2); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth2, authSource1)); verify(baypassSchemeMock, times(2)).createCommand(auth2, authSource1); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0002", auth1, authSource1)); - verify(baypassSchemeMock, times(3)).createCommand(auth1, authSource1); + verify(baypassSchemeMock, times(2)).createCommand(auth1, authSource1); serviceAuthenticationService.evictCacheAllService(); + cacheManager.getCache(CACHE_BY_AUTHENTICATION).clear(); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth1, authSource1)); - verify(baypassSchemeMock, times(4)).createCommand(auth1, authSource1); + verify(baypassSchemeMock, times(3)).createCommand(auth1, authSource1); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth1, authSource2)); verify(baypassSchemeMock, times(3)).createCommand(auth1, authSource2); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0001", auth2, authSource2)); verify(baypassSchemeMock, times(1)).createCommand(auth2, authSource2); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0002", auth1, authSource1)); - verify(baypassSchemeMock, times(5)).createCommand(auth1, authSource1); + verify(baypassSchemeMock, times(3)).createCommand(auth1, authSource1); assertSame(command, serviceAuthenticationService.getAuthenticationCommand("service0002", auth2, authSource1)); verify(baypassSchemeMock, times(3)).createCommand(auth2, authSource1); } diff --git a/gateway-service/src/test/resources/application-test.yml b/gateway-service/src/test/resources/application-test.yml index 3988251ec6..c94f2eacaa 100644 --- a/gateway-service/src/test/resources/application-test.yml +++ b/gateway-service/src/test/resources/application-test.yml @@ -63,9 +63,6 @@ spring: output: ansi: enabled: detect - cache: - ehcache: - config: classpath:ehcache.xml main: allow-bean-definition-overriding: true banner-mode: ${apiml.banner:"off"} diff --git a/gateway-service/src/test/resources/application.yml b/gateway-service/src/test/resources/application.yml index 1230908692..b43df46efd 100644 --- a/gateway-service/src/test/resources/application.yml +++ b/gateway-service/src/test/resources/application.yml @@ -78,9 +78,6 @@ spring: output: ansi: enabled: detect - cache: - ehcache: - config: classpath:ehcache.xml main: allow-bean-definition-overriding: true allow-circular-references: true diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 498498fe8b..ce1faf8211 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -41,7 +41,7 @@ dependencyResolutionManagement { prefer '2.7' } version('commonsFileUpload', '1.5') - version('ehCache', '2.10.9.2') + version('ehCache', '3.10.8') version('eureka', '1.10.18') version('findBugs', '3.0.2') version('githubClassgraph', '4.8.154') @@ -222,7 +222,7 @@ dependencyResolutionManagement { library('bcpkix', 'org.bouncycastle', 'bcpkix-jdk15on').versionRef('bouncyCastle') library('bootstrap', 'org.webjars', 'bootstrap').versionRef('bootstrap') library('commons_io', 'commons-io', 'commons-io').versionRef('commonsIo') - library('eh_cache', 'net.sf.ehcache', 'ehcache').versionRef('ehCache') + library('eh_cache', 'org.ehcache', 'ehcache').versionRef('ehCache') library('eureka_client', 'com.netflix.eureka', 'eureka-client').versionRef('eureka') library('eureka_core', 'com.netflix.eureka', 'eureka-core').versionRef('eureka') library('findbugs', 'com.google.code.findbugs', 'jsr305').versionRef('findBugs') From e2cc9a24d92173650152433f7a8d4c1de9b5cfbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jare=C5=A1?= Date: Mon, 2 Oct 2023 18:13:08 +0200 Subject: [PATCH 2/3] code review and fix for z/OS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pavel Jareš --- .../main/java/org/zowe/apiml/util/CacheUtils.java | 4 ++-- .../service/ServiceAuthenticationServiceImpl.java | 15 +++++---------- gateway-service/src/main/resources/ehcache.xml | 3 ++- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java b/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java index 82222aae48..a1aaafb3e4 100644 --- a/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java +++ b/common-service-core/src/main/java/org/zowe/apiml/util/CacheUtils.java @@ -66,8 +66,8 @@ public void evictSubset(CacheManager cacheManager, String cacheName, Predicate> spliterator = ((javax.cache.Cache) nativeCache).spliterator(); Set keysToRemove = StreamSupport.stream(spliterator, true) - // if entry is compositeKey and first param is the same filter it to be removed or - // if key is not composite key (unknown for evict) evict record (as failover) + // if the key matches the predicate then evict the record or + // if the key is not compositeKey (unknown for evict) evict record (as failover) .filter(e -> !(e.getKey() instanceof CompositeKey) || keyPredicate.test((CompositeKey) e.getKey())) .map(javax.cache.Cache.Entry::getKey) .collect(Collectors.toSet()); diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java index 139bb1bf6e..0da2a5a050 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/security/service/ServiceAuthenticationServiceImpl.java @@ -42,18 +42,13 @@ *

* The main idea of this bean is to create command * {@link AuthenticationCommand}. Command is object which update the - * request for specific scheme (defined by service). This bean is responsible for getting the right command. If it is - * possible to decide now for just one scheme type, bean return this command to update request immediately. - * This command write in the ZUUL context - * UniversalAuthenticationCommand, which is used in Ribbon loadbalancer. There is a listener which work with this value. - * After load balancer will decide which instance will be used, universal command is called and update the request. + * request for specific scheme (defined by service). This bean is responsible for getting the right command. It finds + * just first authentication definition (there is an assumption that all instances of one service have the same + * authentication scheme). *

* All those operation are cached: - * - serviceAuthenticationByAuthentication - * - it caches command which can be deside only by serviceId (in pre filter) - * - serviceAuthenticationByAuthentication - * - it caches commands by {@link Authentication}, it could be in pre filters and - * also in loadbalancer + * - serviceAuthenticationByAuthentication (by authentication scheme and the source) + * - serviceAuthenticationByServiceId (by serviceId, authentication scheme and the source) */ @Service @RequiredArgsConstructor diff --git a/gateway-service/src/main/resources/ehcache.xml b/gateway-service/src/main/resources/ehcache.xml index e7d2c3241e..46e90bf363 100644 --- a/gateway-service/src/main/resources/ehcache.xml +++ b/gateway-service/src/main/resources/ehcache.xml @@ -2,7 +2,7 @@ + xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.6.xsd"> @@ -20,6 +20,7 @@ 1 10 + From 4d1c647bafd744e57f08d4d8e3f86d69e526f35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Jare=C5=A1?= Date: Tue, 3 Oct 2023 14:40:50 +0200 Subject: [PATCH 3/3] set log level of ehcache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pavel Jareš --- api-catalog-services/src/main/resources/application.yml | 4 ++-- api-catalog-services/src/test/resources/application.yml | 4 ++-- caching-service/src/main/resources/application.yml | 2 +- discovery-service/src/main/resources/application.yml | 4 ++-- gateway-service/src/main/resources/application.yml | 4 ++-- gateway-service/src/test/resources/application-test.yml | 2 +- gateway-service/src/test/resources/application.yml | 2 +- metrics-service/src/main/resources/application.yml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/api-catalog-services/src/main/resources/application.yml b/api-catalog-services/src/main/resources/application.yml index c1573c49d3..d3a1554642 100644 --- a/api-catalog-services/src/main/resources/application.yml +++ b/api-catalog-services/src/main/resources/application.yml @@ -33,7 +33,7 @@ logging: com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient: OFF com.netflix.discovery.DiscoveryClient: OFF org.springframework.boot.web.embedded.tomcat.TomcatWebServer: INFO - net.sf.ehcache: WARN + org.ehcache: WARN org.springframework.security.config.annotation.web.builders.WebSecurity: ERROR # New Config @@ -206,7 +206,7 @@ logging: org.apache: INFO org.apache.http: DEBUG com.netflix: INFO - net.sf.ehcache: INFO + org.ehcache: INFO com.netflix.discovery.shared.transport.decorator: DEBUG --- diff --git a/api-catalog-services/src/test/resources/application.yml b/api-catalog-services/src/test/resources/application.yml index d232c8f9ed..695ea0f7ed 100644 --- a/api-catalog-services/src/test/resources/application.yml +++ b/api-catalog-services/src/test/resources/application.yml @@ -30,7 +30,7 @@ logging: com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient: OFF com.netflix.discovery.DiscoveryClient: OFF org.springframework.boot.web.embedded.tomcat.TomcatWebServer: INFO - net.sf.ehcache: WARN + org.ehcache: WARN # New Config org.apache: WARN #org.apache.catalina, org.apache.coyote, org.apache.tomcat @@ -191,7 +191,7 @@ logging: org.apache: INFO org.apache.http: DEBUG com.netflix: INFO - net.sf.ehcache: INFO + org.ehcache: INFO --- spring: diff --git a/caching-service/src/main/resources/application.yml b/caching-service/src/main/resources/application.yml index fe2b0291ce..693e159fe3 100644 --- a/caching-service/src/main/resources/application.yml +++ b/caching-service/src/main/resources/application.yml @@ -168,7 +168,7 @@ logging: com.netflix: INFO org.hibernate: INFO org.springframework.web.servlet.PageNotFound: WARN - net.sf.ehcache: INFO + org.ehcache: INFO org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter: INFO com.netflix.discovery.shared.transport.decorator: DEBUG diff --git a/discovery-service/src/main/resources/application.yml b/discovery-service/src/main/resources/application.yml index ee8a19c5dd..b27832dc38 100644 --- a/discovery-service/src/main/resources/application.yml +++ b/discovery-service/src/main/resources/application.yml @@ -11,7 +11,7 @@ logging: com.netflix.discovery.DiscoveryClient: OFF org.springframework.boot.web.embedded.tomcat.TomcatWebServer: INFO com.sun.jersey.server.impl.application.WebApplicationImpl: WARN - net.sf.ehcache: WARN + org.ehcache: WARN org.springframework.security.config.annotation.web.builders.WebSecurity: ERROR # New Config @@ -165,7 +165,7 @@ logging: org.apache.http: DEBUG com.netflix: INFO com.sun.jersey.server.impl.application.WebApplicationImpl: INFO - net.sf.ehcache: INFO + org.ehcache: INFO com.netflix.discovery.shared.transport.decorator: DEBUG --- diff --git a/gateway-service/src/main/resources/application.yml b/gateway-service/src/main/resources/application.yml index 9b20ea2dd9..eb1b64dea3 100644 --- a/gateway-service/src/main/resources/application.yml +++ b/gateway-service/src/main/resources/application.yml @@ -14,7 +14,7 @@ logging: org.zowe.apiml.gateway.error: INFO org.eclipse.jetty: WARN org.springframework.web.servlet.PageNotFound: ERROR - net.sf.ehcache: WARN + org.ehcache: WARN org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter: ERROR org.springframework.security.config.annotation.web.builders.WebSecurity: ERROR org.springframework.cloud.client.loadbalancer.reactive.[ReactorLoadBalancerClientAutoConfiguration$ReactorLoadBalancerClientRibbonWarnLogger]: ERROR @@ -295,7 +295,7 @@ logging: com.netflix: INFO org.hibernate: INFO org.springframework.web.servlet.PageNotFound: WARN - net.sf.ehcache: INFO + org.ehcache: INFO org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter: INFO com.netflix.discovery.shared.transport.decorator: DEBUG org.zowe.apiml.gateway.ws: DEBUG diff --git a/gateway-service/src/test/resources/application-test.yml b/gateway-service/src/test/resources/application-test.yml index c94f2eacaa..4c25b57ba6 100644 --- a/gateway-service/src/test/resources/application-test.yml +++ b/gateway-service/src/test/resources/application-test.yml @@ -222,7 +222,7 @@ logging: com.netflix: INFO org.hibernate: INFO org.springframework.web.servlet.PageNotFound: WARN - net.sf.ehcache: INFO + org.ehcache: INFO org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter: INFO --- diff --git a/gateway-service/src/test/resources/application.yml b/gateway-service/src/test/resources/application.yml index b43df46efd..dda5fb2ff8 100644 --- a/gateway-service/src/test/resources/application.yml +++ b/gateway-service/src/test/resources/application.yml @@ -241,7 +241,7 @@ logging: com.netflix: INFO org.hibernate: INFO org.springframework.web.servlet.PageNotFound: WARN - net.sf.ehcache: INFO + org.ehcache: INFO org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter: INFO --- diff --git a/metrics-service/src/main/resources/application.yml b/metrics-service/src/main/resources/application.yml index bf3fd6d764..c19490b3c9 100644 --- a/metrics-service/src/main/resources/application.yml +++ b/metrics-service/src/main/resources/application.yml @@ -147,7 +147,7 @@ logging: com.netflix: INFO org.hibernate: INFO org.springframework.web.servlet.PageNotFound: WARN - net.sf.ehcache: INFO + org.ehcache: INFO org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter: INFO ---