/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
* contributors by the @authors tag. See the copyright.txt in the
* distribution for a full listing of individual contributors.
*
* 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.as.quickstarts.ejb.multi.server.app;
import java.security.Principal;
import java.util.Properties;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.logging.Logger;
/**
* <p>
* An example how to use the new features 'scoped client' introduced with
* EJBCLIENT-34 in AS7.2.0 or EAP6.1.<br/>
* If a server without that feature is used the outbound-connection will be used
* and the behavior is different.
* </p>
* <p>
* The functionality will be the same as MainAppBean provide, the interface
* @{link MainApp} will be shared to use both.<br/>
* The sub applications, deployed in different servers are called direct by
* using the ejb-client scoped context properties.
* </p>
*
* @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a>
*/
@Stateless
public class MainEjbClient34AppBean implements MainApp {
private static final Logger LOGGER = Logger.getLogger(MainEjbClient34AppBean.class);
@Resource
SessionContext context;
@Override
public String getJBossNodeName() {
return System.getProperty("jboss.node.name");
}
@Override
public String invokeAll(String text) {
Principal caller = context.getCallerPrincipal();
LOGGER.info("[" + caller.getName() + "] " + text);
final StringBuilder result = new StringBuilder("MainEjbClient34App["+ caller.getName() + "]@" + getJBossNodeName());
// Call AppOne with the direct ejb: naming
try {
result.append(" > [ " + invokeAppOne(text));
} catch (Exception e) {
LOGGER.error("Could not invoke AppOne", e);
}
result.append(" > " + invokeAppTwo(text));
result.append(" ]");
return result.toString();
}
/**
* Invoke the AppOne with the scoped client context. The initial connection
* will use the 'quickuser1', to differentiate the cluster connection it
* will be use the user 'quickuser2' to see if the clustered context is used
* or not.
*
* @param text
* Simple text which will be logged at server side.
* @return simple collection of the returned results
*/
private String invokeAppOne(String text) {
Context iCtx = null;
final Properties ejbClientContextProps = new Properties();
ejbClientContextProps.put("endpoint.name", "appMain->appOne_endpoint");
// --- Property to enable scoped EJB client context which will be tied
// to the JNDI context ---
ejbClientContextProps.put("org.jboss.ejb.client.scoped.context", true);
// Property which will handle the ejb: namespace during JNDI lookup
ejbClientContextProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
ejbClientContextProps.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED","false");
// add a property which lists the connections that we are configuring.
// In this example, we are just configuring a single connection.
final String connectionName = "appOneConnection";
ejbClientContextProps.put("remote.connections", connectionName);
// add the properties to connect the app-one host
ejbClientContextProps.put("remote.connection." + connectionName + ".host", "localhost");
ejbClientContextProps.put("remote.connection." + connectionName + ".port", "4547");
ejbClientContextProps.put("remote.connection." + connectionName + ".username", "quickuser1");
ejbClientContextProps.put("remote.connection." + connectionName + ".password", "quick123+");
ejbClientContextProps.put("remote.clusters", "ejb");
ejbClientContextProps.put("remote.cluster.ejb.username", "quickuser2");
ejbClientContextProps.put("remote.cluster.ejb.password", "quick+123");
try {
// this context will not use the server configured
// 'outbound-connection' and also did not use the
// jboss-ejb-client.xml.
iCtx = new InitialContext(ejbClientContextProps);
final AppOne bean = (AppOne) iCtx.lookup("ejb:jboss-ejb-multi-server-app-one/ejb//AppOneBean!" + AppOne.class.getName());
StringBuffer result = new StringBuffer("{");
for (int i = 0; i < 8; i++) {
// invoke on the bean
final String appOneResult = bean.invoke(text);
if (i > 0) {
result.append(", ");
}
result.append(appOneResult);
}
result.append("}");
LOGGER.info("AppOne (loop) returns : " + result);
return result.toString();
} catch (NamingException e) {
LOGGER.error("Could not invoke appOne", e);
return null;
} finally {
saveContextClose(iCtx);
}
}
/**
* Close the given context and write a log message which endpoint is closed.
*
* @param iCtx
* context to close, <code>null</code> will be ignored.
*/
private static void saveContextClose(Context iCtx) {
if (iCtx != null) {
try {
LOGGER.info("close Context "+ iCtx.getEnvironment().get("endpoint.name"));
iCtx.close();
} catch (NamingException e) {
LOGGER.error("InitialContext can not be closed", e);
}
}
}
/**
* Invoke the App2 with different ejb-client context. The server AppTwoA
* will be called with the user quickuser1. The server AppTwoB will be
* called with the user quickuser2. Both invocations are separate, there
* will no mix between. Also the outbound-connection is not used.
*
* @param text
* Simple text which will be logged at server side.
* @return simple collection of the returned results
*/
private String invokeAppTwo(String text) {
AppTwo beanA = null;
AppTwo beanB = null;
final Properties ejbClientContextProps = new Properties();
ejbClientContextProps.put("endpoint.name", "appMain->appTwoA_endpoint");
// Property to enable scoped EJB client context which will be tied to
// the JNDI context
ejbClientContextProps.put("org.jboss.ejb.client.scoped.context", true);
// Property which will handle the ejb: namespace during JNDI lookup
ejbClientContextProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final String connectionName = "appTwoConnection";
ejbClientContextProps.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
// add the properties to connect the app-one host
ejbClientContextProps.put("remote.connections", connectionName);
ejbClientContextProps.put("remote.connection." + connectionName + ".host", "localhost");
ejbClientContextProps.put("remote.connection." + connectionName + ".port", "4647");
ejbClientContextProps.put("remote.connection." + connectionName + ".username", "quickuser1");
ejbClientContextProps.put("remote.connection." + connectionName + ".password", "quick123+");
Context iCtxA = null;
try {
iCtxA = new InitialContext(ejbClientContextProps);
beanA = (AppTwo) iCtxA.lookup("ejb:jboss-ejb-multi-server-app-two/ejb//AppTwoBean!" + AppTwo.class.getName());
} catch (NamingException e) {LOGGER.error("Could not create InitialContext('appTwoA')");}
// change the necessary properties to call the other server
ejbClientContextProps.put("endpoint.name", "appMain->appTwoB_endpoint");
ejbClientContextProps.put("remote.connection." + connectionName + ".port", "5247");
ejbClientContextProps.put("remote.connection." + connectionName + ".username", "quickuser2");
ejbClientContextProps.put("remote.connection." + connectionName + ".password", "quick+123");
Context iCtxB = null;
try {
iCtxB = new InitialContext(ejbClientContextProps);
beanB = (AppTwo) iCtxB.lookup("ejb:jboss-ejb-multi-server-app-two/ejb//AppTwoBean!" + AppTwo.class.getName());
} catch (NamingException e) {
LOGGER.error("Could not create InitialContext('appTwoB')");
}
StringBuffer result = new StringBuffer(" appTwo loop(4 time A-B expected){");
for (int i = 0; i < 4; i++) {
// invoke on the bean
String appResult = beanA.invokeSecured(text);
if (i > 0) {
result.append(", ");
}
result.append(appResult);
appResult = beanB.invokeSecured(text);
result.append(", ");
result.append(appResult);
}
result.append("}");
LOGGER.info("AppTwo (loop) returns : " + result);
// should be closed and null the reference to close the connection
saveContextClose(iCtxA);
iCtxA = null;
saveContextClose(iCtxB);
iCtxB = null;
return result.toString();
}
}