Skip to content

Commit

Permalink
[EJBCLIENT-311] Add timeout for discovering the destination of an EJB…
Browse files Browse the repository at this point in the history
  • Loading branch information
iweiss committed Feb 20, 2019
1 parent 30a5f89 commit 1daf928
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import javax.ejb.NoSuchEJBException;
Expand All @@ -56,6 +57,7 @@
import org.wildfly.discovery.ServiceURL;
import org.wildfly.discovery.ServicesQueue;
import org.wildfly.naming.client.NamingProvider;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
* The EJB client interceptor responsible for discovering the destination of a request. If a destination is already
Expand All @@ -71,7 +73,8 @@ public final class DiscoveryEJBClientInterceptor implements EJBClientInterceptor

private static final String[] NO_STRINGS = new String[0];
private static final boolean WILDFLY_TESTSUITE_HACK = Boolean.getBoolean("org.jboss.ejb.client.wildfly-testsuite-hack");

// This provides a way timeout a discovery, avoiding blocking on some edge cases. See EJBCLIENT-311.
private static final long DISCOVERY_TIMEOUT = Long.parseLong(WildFlySecurityManager.getPropertyPrivileged("org.jboss.ejb.client.discovery.timeout", "0"));

/**
* This interceptor's priority.
Expand Down Expand Up @@ -312,7 +315,7 @@ private List<Throwable> doFirstMatchDiscovery(AbstractInvocationContext context,
final Set<URI> set = context.getAttachment(BL_KEY);
try (final ServicesQueue queue = discover(filterSpec)) {
ServiceURL serviceURL;
while ((serviceURL = queue.takeService()) != null) {
while ((serviceURL = queue.takeService(DISCOVERY_TIMEOUT, TimeUnit.SECONDS)) != null) {
final URI location = serviceURL.getLocationURI();
if (set == null || ! set.contains(location)) {
// Got a match! See if there's a node affinity to set for the invocation.
Expand Down Expand Up @@ -370,7 +373,7 @@ private List<Throwable> doAnyDiscovery(AbstractInvocationContext context, final
int nodeless = 0;
try (final ServicesQueue queue = discover(filterSpec)) {
ServiceURL serviceURL;
while ((serviceURL = queue.takeService()) != null) {
while ((serviceURL = queue.takeService(DISCOVERY_TIMEOUT, TimeUnit.SECONDS)) != null) {
final URI location = serviceURL.getLocationURI();
if (blacklist == null || ! blacklist.contains(location)) {
// Got a match! See if there's a node affinity to set for the invocation.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2019 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.ejb.client.test;

import javax.ejb.NoSuchEJBException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import org.jboss.ejb.client.EJBClient;
import org.jboss.ejb.client.EJBClientConnection;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.StatelessEJBLocator;
import org.jboss.ejb.client.URIAffinity;
import org.jboss.ejb.client.legacy.JBossEJBProperties;
import org.jboss.ejb.client.test.common.DummyServer;
import org.jboss.ejb.client.test.common.Echo;
import org.jboss.ejb.client.test.common.EchoBean;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* @author <a href="ingo@redhat.com">Ingo Weiss</a>
*/
public class RemoteDiscoveryTimeoutTestCase {
private static final Logger logger = Logger.getLogger(RemoteDiscoveryTimeoutTestCase.class);
private static final String PROPERTIES_FILE = "no-protocol-jboss-ejb-client.properties";

private DummyServer server;
private boolean serverStarted = false;

// module
private static final String APP_NAME = "my-foo-app";
private static final String MODULE_NAME = "my-bar-module";
private static final String DISTINCT_NAME = "";

private static final String SERVER_NAME = "test-server";

/**
* Do any general setup here
* @throws Exception
*/
@BeforeClass
public static void beforeClass() throws Exception {
// trigger the static init of the correct properties file - this also depends on running in forkMode=always
JBossEJBProperties ejbProperties = JBossEJBProperties.fromClassPath(RemoteDiscoveryTimeoutTestCase.class.getClassLoader(), PROPERTIES_FILE);
JBossEJBProperties.getContextManager().setGlobalDefault(ejbProperties);
}

/**
* Do any test specific setup here
*/
@Before
public void beforeTest() throws Exception {
// start a server
server = new DummyServer("localhost", 6999, SERVER_NAME);
server.start();
serverStarted = true;
logger.info("Started server ...");

server.register(APP_NAME, MODULE_NAME, DISTINCT_NAME, Echo.class.getSimpleName(), new EchoBean());
logger.info("Registered module ...");
}

/**
* Do any test-specific tear down here.
*/
@After
public void afterTest() {
server.unregister(APP_NAME, MODULE_NAME, DISTINCT_NAME, Echo.class.getName());
logger.info("Unregistered module ...");

if (serverStarted) {
try {
this.server.stop();
} catch (Throwable t) {
logger.info("Could not stop server", t);
}
}
logger.info("Stopped server ...");
}

/**
* Test a failed client discovery
*/
@Test
public void testClientDiscoveryTimeout() throws InterruptedException {
logger.info("Testing client discovery timeout of 10 seconds");
System.setProperty("org.jboss.ejb.client.discovery.timeout", "10");
String errorMessage = "";

try {
// create a proxy for invocation
final StatelessEJBLocator<Echo> statelessEJBLocator = new StatelessEJBLocator<>
(Echo.class, APP_NAME, MODULE_NAME, Echo.class.getSimpleName(), DISTINCT_NAME);
final Echo proxy = EJBClient.createProxy(statelessEJBLocator);
Assert.assertNotNull("Received a null proxy", proxy);
logger.info("Created proxy for Echo: " + proxy.toString());

logger.info("Invoking on proxy...");
// Invoke on the proxy. This should fail in 10 seconds or else it'll hang.
final String message = "hello!";
final String echo = proxy.echo(message);
} catch (NoSuchEJBException nsee) {
errorMessage = nsee.getMessage();
}

Assert.assertTrue("Wrong error message. Expected EJBCLIENT000079.", errorMessage.contains("EJBCLIENT000079"));
}
}
28 changes: 28 additions & 0 deletions src/test/resources/no-protocol-jboss-ejb-client.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# JBoss, Home of Professional Open Source.
# Copyright 2019 Red Hat, Inc., and individual contributors
# as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=one

# connection to a node at protocol://host:port
remote.connection.one.host=localhost
remote.connection.one.port=6999
remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.one.username=test
remote.connection.one.password=test

0 comments on commit 1daf928

Please sign in to comment.