From c579c1a1acc2414b724c082390a6a4676540366d Mon Sep 17 00:00:00 2001 From: lprimak Date: Thu, 8 Apr 2021 19:37:56 -0500 Subject: [PATCH] - fix race condition leading to duplicate initialization of Micro ports - moved identity store addition code to @BeforeClass - added Payara Client deps to samples test - updated Arquillian to Alpha9 - update to Arquillian Connectors 2.4.1 - Updated surefire plugin to -M5 --- .../micro/services/PayaraInstanceImpl.java | 84 +++++++++---------- .../services/data/InstanceDescriptorImpl.java | 33 ++++---- appserver/tests/payara-samples/pom.xml | 8 +- .../servlet/JAXRSRolesAllowedEETest.java | 11 ++- .../samples/realm-identity-stores/pom.xml | 11 +++ ...tipleRealmIdentityStoreDefinitionTest.java | 7 +- pom.xml | 4 +- 7 files changed, 90 insertions(+), 68 deletions(-) diff --git a/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/PayaraInstanceImpl.java b/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/PayaraInstanceImpl.java index fb9a2ba2f32..50aff672fc7 100644 --- a/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/PayaraInstanceImpl.java +++ b/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/PayaraInstanceImpl.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) 2016-2020 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2016-2021 Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -95,6 +95,8 @@ import fish.payara.nucleus.hazelcast.HazelcastCore; import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.glassfish.grizzly.utils.Holder.LazyHolder; +import static org.glassfish.grizzly.utils.Holder.lazyHolder; /** * Internal Payara Service for describing instances @@ -140,7 +142,7 @@ public class PayaraInstanceImpl implements EventListener, MessageReceiver, Payar private String instanceName; private String instanceGroup; - private InstanceDescriptorImpl me; + private final LazyHolder descriptor = lazyHolder(this::initialiseInstanceDescriptor); @Inject private ServerEnvironment environment; @@ -153,13 +155,7 @@ public class PayaraInstanceImpl implements EventListener, MessageReceiver, Payar @Inject private PayaraExecutorService executor; - - private synchronized InstanceDescriptorImpl getMyInstanceDescriptor() { - if (me == null) { - initialiseInstanceDescriptor(); - } - return me; - } + @Override public String getInstanceName() { @@ -169,7 +165,7 @@ public String getInstanceName() { @Override public void setInstanceName(String instanceName) { this.instanceName = instanceName; - me.setInstanceName(instanceName); + descriptor.get().setInstanceName(instanceName); } @Override @@ -246,32 +242,32 @@ void postConstruct() { @SuppressWarnings({"unchecked"}) public void event(Event event) { if (event.is(EventTypes.SERVER_READY)) { - PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.ADDED, getMyInstanceDescriptor()); + PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.ADDED, descriptor.get()); ClusterMessage message = new ClusterMessage<>(pie); this.cluster.getEventBus().publish(INTERNAL_EVENTS_NAME, message); for (String appName : appRegistry.getAllApplicationNames()) { - getMyInstanceDescriptor().addApplication(new ApplicationDescriptorImpl(appRegistry.get(appName))); + descriptor.get().addApplication(new ApplicationDescriptorImpl(appRegistry.get(appName))); } - cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor()); + cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, descriptor.get()); executor.scheduleAtFixedRate(() -> { - getMyInstanceDescriptor().setLastHeartBeat(System.currentTimeMillis()); + descriptor.get().setLastHeartBeat(System.currentTimeMillis()); if (myCurrentID != null) { - cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor()); + cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, descriptor.get()); } }, 0, 5, TimeUnit.SECONDS); } // Adds the application to the clustered register of deployed applications else if (event.is(Deployment.APPLICATION_STARTED)) { if (event.hook() != null && event.hook() instanceof ApplicationInfo) { ApplicationInfo applicationInfo = (ApplicationInfo) event.hook(); - getMyInstanceDescriptor().addApplication(new ApplicationDescriptorImpl(applicationInfo)); + descriptor.get().addApplication(new ApplicationDescriptorImpl(applicationInfo)); logger.log(Level.FINE, "App Loaded: {2}, Enabled: {0}, my ID: {1}", new Object[] { hazelcast.isEnabled(), myCurrentID, applicationInfo.getName() }); - cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor()); + cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, descriptor.get()); } } - // ensures the same application id is used when there is a deployment + // ensures the same application id is used when there is a deployment // if the application id is in the cluster keyed by application name else if (event.is(Deployment.APPLICATION_PREPARED)) { if (event.hook() != null && event.hook() instanceof DeploymentContext) { @@ -291,11 +287,11 @@ else if (event.is(Deployment.APPLICATION_PREPARED)) { else if (event.is(Deployment.APPLICATION_UNLOADED)) { if (event.hook() != null && event.hook() instanceof ApplicationInfo) { ApplicationInfo applicationInfo = (ApplicationInfo) event.hook(); - getMyInstanceDescriptor().removeApplication(new ApplicationDescriptorImpl(applicationInfo)); - cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, getMyInstanceDescriptor()); + descriptor.get().removeApplication(new ApplicationDescriptorImpl(applicationInfo)); + cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, descriptor.get()); } } else if (event.is(HazelcastEvents.HAZELCAST_SHUTDOWN_STARTED)) { - PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.REMOVED, getMyInstanceDescriptor()); + PayaraInternalEvent pie = new PayaraInternalEvent(PayaraInternalEvent.MESSAGE.REMOVED, descriptor.get()); ClusterMessage message = new ClusterMessage<>(pie); this.cluster.getClusteredStore().remove(INSTANCE_STORE_NAME, myCurrentID); this.cluster.getEventBus().publish(INTERNAL_EVENTS_NAME, message); @@ -303,7 +299,7 @@ else if (event.is(Deployment.APPLICATION_UNLOADED)) { // When Hazelcast is bootstrapped, update the instance descriptor with any new information if (event.is(HazelcastEvents.HAZELCAST_BOOTSTRAP_COMPLETE)) { - initialiseInstanceDescriptor(); + descriptor.get(); logger.log(Level.FINE, "Hz Bootstrap Complete, Enabled: {0}, my ID: {1}", new Object[] { hazelcast.isEnabled(), myCurrentID }); // remove listener first cluster.getEventBus().removeMessageReceiver(INTERNAL_EVENTS_NAME, this); @@ -314,7 +310,7 @@ else if (event.is(Deployment.APPLICATION_UNLOADED)) { // If the generated name had to be changed, update the instance descriptor with the new information if (event.is(HazelcastEvents.HAZELCAST_GENERATED_NAME_CHANGE)) { - initialiseInstanceDescriptor(); + descriptor.get(); } } @@ -334,7 +330,7 @@ public Set getClusteredPayaras() { @Override public void publishCDIEvent(PayaraClusteredCDIEvent event) { if (event.getInstanceDescriptor() == null) { - event.setId(me); + event.setId(descriptor.get()); } ClusterMessage message = new ClusterMessage<>(event); cluster.getEventBus().publish(CDI_EVENTS_NAME, message); @@ -362,7 +358,7 @@ public void addCDIListener(CDIEventListener listener) { @Override public InstanceDescriptor getLocalDescriptor() { - return me; + return descriptor.get(); } @Override @@ -374,7 +370,7 @@ public InstanceDescriptorImpl getDescriptor(UUID member) { return result; } - private void initialiseInstanceDescriptor() { + private InstanceDescriptorImpl initialiseInstanceDescriptor() { boolean liteMember = false; int hazelcastPort = 5900; InetAddress hostname = null; @@ -399,7 +395,7 @@ private void initialiseInstanceDescriptor() { List ports = new ArrayList<>(); List sslPorts = new ArrayList<>(); int adminPort = 0; - for (NetworkListener networkListener : + for (NetworkListener networkListener : context.getConfigBean().getConfig().getNetworkConfig().getNetworkListeners().getNetworkListener()) { // Try and get the port. First get the port in the domain xml, then attempt to get the dynamic config port. @@ -444,45 +440,43 @@ private void initialiseInstanceDescriptor() { // Initialise the instance descriptor and set all of its attributes try { + InstanceDescriptorImpl instanceDescriptor = new InstanceDescriptorImpl(myCurrentID); // If Hazelcast is being rebooted dynamically, we don't want to lose the already registered applications - Collection deployedApplications = new ArrayList<>(); - if (me != null) { - deployedApplications = me.getDeployedApplications(); - } - me = new InstanceDescriptorImpl(myCurrentID); - me.setInstanceName(instanceName); - me.setInstanceGroup(instanceGroup); + Collection deployedApplications = instanceDescriptor.getDeployedApplications(); + instanceDescriptor.setInstanceName(instanceName); + instanceDescriptor.setInstanceGroup(instanceGroup); for (int port : ports) { - me.addHttpPort(port); + instanceDescriptor.addHttpPort(port); } for (int sslPort : sslPorts) { - me.addHttpsPort(sslPort); + instanceDescriptor.addHttpsPort(sslPort); } - me.setAdminPort(adminPort); - me.setHazelcastPort(hazelcastPort); - me.setLiteMember(liteMember); - me.setInstanceType(instanceType); + instanceDescriptor.setAdminPort(adminPort); + instanceDescriptor.setHazelcastPort(hazelcastPort); + instanceDescriptor.setLiteMember(liteMember); + instanceDescriptor.setInstanceType(instanceType); if (hostname != null) { - me.setHostName(hostname); + instanceDescriptor.setHostName(hostname); } - // If there were some deployed applications from the previous instance descriptor, register them with the new + // If there were some deployed applications from the previous instance descriptor, register them with the new // one if (!deployedApplications.isEmpty()) { for (ApplicationDescriptor application : deployedApplications) { - me.addApplication(application); + instanceDescriptor.addApplication(application); } } // Register the instance descriptor to the cluster if it's enabled if (cluster.isEnabled()) { - cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, me); + cluster.getClusteredStore().set(INSTANCE_STORE_NAME, myCurrentID, instanceDescriptor); } + return instanceDescriptor; } catch (UnknownHostException ex) { - logger.log(Level.SEVERE, "Could not find local hostname", ex); + throw new RuntimeException(ex); } } diff --git a/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/data/InstanceDescriptorImpl.java b/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/data/InstanceDescriptorImpl.java index 4d690d79c0b..96e751da653 100644 --- a/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/data/InstanceDescriptorImpl.java +++ b/appserver/payara-appserver-modules/payara-micro-service/src/main/java/fish/payara/appserver/micro/services/data/InstanceDescriptorImpl.java @@ -2,7 +2,7 @@ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - Copyright (c) 2016-2020 Payara Foundation. All rights reserved. + Copyright (c) 2016-2021 Payara Foundation. All rights reserved. The contents of this file are subject to the terms of the Common Development and Distribution License("CDDL") (collectively, the "License"). You @@ -25,7 +25,6 @@ and Distribution License("CDDL") (collectively, the "License"). You import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -46,6 +45,10 @@ and Distribution License("CDDL") (collectively, the "License"). You import fish.payara.micro.data.ApplicationDescriptor; import fish.payara.micro.data.InstanceDescriptor; import fish.payara.micro.data.ModuleDescriptor; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.UUID; /** @@ -58,8 +61,8 @@ public class InstanceDescriptorImpl implements InstanceDescriptor { private final UUID memberUUID; private String instanceName; - private final List httpPorts; - private final List httpsPorts; + private final Set httpPorts; + private final Set httpsPorts; private InetAddress hostName; private Map deployedApplications; private boolean liteMember; @@ -72,8 +75,8 @@ public class InstanceDescriptorImpl implements InstanceDescriptor { public InstanceDescriptorImpl(UUID uuid) throws UnknownHostException { hostName = InetAddress.getLocalHost(); memberUUID = uuid; - httpPorts = new ArrayList<>(); - httpsPorts = new ArrayList<>(); + httpPorts = new LinkedHashSet<>(); + httpsPorts = new LinkedHashSet<>(); heartBeatTS = System.currentTimeMillis(); } @@ -116,7 +119,7 @@ public UUID getMemberUUID() { */ @Override public List getHttpPorts() { - return httpPorts; + return Collections.unmodifiableList(new ArrayList<>(httpPorts)); } /** @@ -157,7 +160,7 @@ public Collection getDeployedApplications() { */ @Override public List getHttpsPorts() { - return httpsPorts; + return Collections.unmodifiableList(new ArrayList<>(httpsPorts)); } /** @@ -342,7 +345,7 @@ private JsonObject toJsonObject(boolean verbose) { }); appBuilder.add("Mappings", servletMappings.build()); } - + // If there's more modules, print info for each module } else { JsonArrayBuilder modules = Json.createArrayBuilder(); @@ -398,7 +401,7 @@ public String toString() { if (memberUUID != null) { sb.append("Hazelcast Member UUID ").append(this.memberUUID).append('\n'); } - + for (ApplicationDescriptor applicationDescriptor : getDeployedApplications()) { sb.append("Deployed: "); sb.append(applicationDescriptor.getName()).append(" ( "); @@ -409,7 +412,7 @@ public String toString() { } else { sb.append("***"); } - + sb.append(" [ "); for (Entry servletMapping : moduleDescriptor.getServletMappings().entrySet()) { sb.append("< ") @@ -419,7 +422,7 @@ public String toString() { sb.append(" ] "); } sb.append(")\n"); - + String libraries = applicationDescriptor.getLibraries(); if (libraries != null) { sb.append(' ').append(applicationDescriptor.getLibraries()); @@ -457,7 +460,7 @@ public List getApplicationURLS() { } return result; } - + /** * Gets the instance group name * @return The instance group name @@ -465,7 +468,7 @@ public List getApplicationURLS() { public String getInstanceGroup() { return instanceGroup; } - + /** * Sets the instance group name * @param instanceGroup The instance group name @@ -473,7 +476,7 @@ public String getInstanceGroup() { public void setInstanceGroup(String instanceGroup) { this.instanceGroup = instanceGroup; } - + public void setLastHeartBeat(long val) { heartBeatTS = val; } diff --git a/appserver/tests/payara-samples/pom.xml b/appserver/tests/payara-samples/pom.xml index cffd3309dfb..3d4e6b09ade 100644 --- a/appserver/tests/payara-samples/pom.xml +++ b/appserver/tests/payara-samples/pom.xml @@ -302,7 +302,7 @@ org.jboss.arquillian arquillian-bom - 1.7.0.Alpha6 + 1.7.0.Alpha9 import pom @@ -534,6 +534,12 @@ 1.7.30 test + + fish.payara.arquillian + payara-client-ee8 + test + true + jakarta.servlet diff --git a/appserver/tests/payara-samples/samples/jaxrs-rolesallowed-servlet/src/test/java/fish/payara/samples/jaxrs/rolesallowed/servlet/JAXRSRolesAllowedEETest.java b/appserver/tests/payara-samples/samples/jaxrs-rolesallowed-servlet/src/test/java/fish/payara/samples/jaxrs/rolesallowed/servlet/JAXRSRolesAllowedEETest.java index b5b996a367a..1d86a91f06d 100644 --- a/appserver/tests/payara-samples/samples/jaxrs-rolesallowed-servlet/src/test/java/fish/payara/samples/jaxrs/rolesallowed/servlet/JAXRSRolesAllowedEETest.java +++ b/appserver/tests/payara-samples/samples/jaxrs-rolesallowed-servlet/src/test/java/fish/payara/samples/jaxrs/rolesallowed/servlet/JAXRSRolesAllowedEETest.java @@ -24,6 +24,7 @@ import static javax.ws.rs.core.MediaType.TEXT_PLAIN; import static org.jboss.shrinkwrap.api.ShrinkWrap.create; import static org.junit.Assert.assertTrue; +import org.junit.BeforeClass; /** * This sample tests that we can install a custom JACC provider @@ -39,10 +40,6 @@ public class JAXRSRolesAllowedEETest { @Deployment(testable = false) public static WebArchive createDeployment() { - if (ServerOperations.isServer()) { - ServerOperations.addUserToContainerIdentityStore("test", "a"); - } - WebArchive archive = create(WebArchive.class) .addAsWebInfResource((new File("src/main/webapp/WEB-INF", "web.xml"))) @@ -57,6 +54,12 @@ public static WebArchive createDeployment() { return archive; } + @BeforeClass + public static void init() { + if (ServerOperations.isServer()) { + ServerOperations.addUserToContainerIdentityStore("test", "a"); + } + } @Test diff --git a/appserver/tests/payara-samples/samples/realm-identity-stores/pom.xml b/appserver/tests/payara-samples/samples/realm-identity-stores/pom.xml index f2a345722e9..56573c3a49d 100644 --- a/appserver/tests/payara-samples/samples/realm-identity-stores/pom.xml +++ b/appserver/tests/payara-samples/samples/realm-identity-stores/pom.xml @@ -39,6 +39,17 @@ made subject to such option by the copyright holder. --> Payara Samples - Payara - Realm Identity Stores war + + + + maven-surefire-plugin + + alphabetical + + + + + io.smallrye diff --git a/appserver/tests/payara-samples/samples/realm-identity-stores/src/test/java/fish/payara/samples/realm/identity/store/MultipleRealmIdentityStoreDefinitionTest.java b/appserver/tests/payara-samples/samples/realm-identity-stores/src/test/java/fish/payara/samples/realm/identity/store/MultipleRealmIdentityStoreDefinitionTest.java index aaaff3b0969..2d6a444681a 100644 --- a/appserver/tests/payara-samples/samples/realm-identity-stores/src/test/java/fish/payara/samples/realm/identity/store/MultipleRealmIdentityStoreDefinitionTest.java +++ b/appserver/tests/payara-samples/samples/realm-identity-stores/src/test/java/fish/payara/samples/realm/identity/store/MultipleRealmIdentityStoreDefinitionTest.java @@ -65,6 +65,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import static org.valid4j.matchers.http.HttpResponseMatchers.hasStatus; @@ -85,7 +86,6 @@ public class MultipleRealmIdentityStoreDefinitionTest { @Deployment(testable = false) public static WebArchive createDeployment() { - ServerOperations.setupContainerFileIdentityStore("new-file-realm"); return create(WebArchive.class) .addClasses( MultipleRealmIdentityStoreAppConfig.class, @@ -96,6 +96,11 @@ public static WebArchive createDeployment() { .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")); } + @BeforeClass + public static void init() { + ServerOperations.setupContainerFileIdentityStore("new-file-realm"); + } + @Before public void addTestUser() { ServerOperations.addUserToContainerIdentityStore("file", DEFAULT_USER, ADMIN); diff --git a/pom.xml b/pom.xml index 4ebc09b2311..acadbcbe68a 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ 3.8.0 true 3.1.1 - 3.0.0-M3 + 3.0.0-M5 3.1.0 2.5.3 3.1.1 @@ -213,7 +213,7 @@ 3.0 2.0 2.0 - 2.3.3 + 2.4.1 0.33.0 1.4.196 1.1.2