How to get an EJB client's IP Address information from an EJB applicaiton in JBoss EAP 7.1 or later
Environment
- Red Hat Enterprise Application Platform (EAP) 7.1 or later
Issue
- How to get an EJB client's IP Address information from an EJB applicaiton in JBoss EAP 7.1 or later
Resolution
The feature is implemented by the following JIRAs and available since JBoss EAP 7.1 or later:
- Content from issues.jboss.org is not included.JBEAP-10135 - Allow access to client IP address on server side during EJB invocation
- Content from issues.jboss.org is not included.EJBCLIENT-208 - Add source IP address to context data
EJB application
import java.net.InetSocketAddress;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import org.jboss.ejb.client.EJBClient;
@Stateless
public class ExampleSLSB implements ExampleRemote {
@Resource
private SessionContext context;
@Override
public String getClientAddress() {
InetSocketAddress clientAddress = (InetSocketAddress) context.getContextData().get(EJBClient.SOURCE_ADDRESS_KEY);
// EJBClient.SOURCE_ADDRESS_KEY == jboss.source-address, so the following is equivalent to the above
// InetSocketAddress clientAddress = (InetSocketAddress) context.getContextData().get("jboss.source-address");
if(clientAddress != null) {
return clientAddress.getAddress().getHostAddress(); // ip-address (e.g. 127.0.0.1)
// return clientAddress.getHostString(); // resolved hostname (e.g. localhost)
// return clientAddress.toString(); // <hostname>/<ip-address>:<port> format (e.g localhost/127.0.0.1:45136)
}
return null;
}
}
EJB Interceptor
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
@Stateless
@Interceptors({ServerSideInterceptor.class})
public class ExampleSLSB implements ExampleRemote {
...
}
import java.net.InetSocketAddress;
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import org.jboss.ejb.client.EJBClient;
public class ServerSideInterceptor {
private static final Logger log = Logger.getLogger(ServerSideInterceptor.class.getName());
@AroundInvoke
public Object checkClientAddress(InvocationContext context) throws Exception {
try {
// Before Invocation
InetSocketAddress clientAddress = (InetSocketAddress) context.getContextData().get(EJBClient.SOURCE_ADDRESS_KEY);
// EJBClient.SOURCE_ADDRESS_KEY == jboss.source-address, so the following is equivalent to the above
// InetSocketAddress clientAddress = (InetSocketAddress) context.getContextData().get("jboss.source-address");
if(clientAddress != null) {
// an ip-address format (e.g. 127.0.0.1)
log.info("Calling client address: " + clientAddress.getAddress().getHostAddress());
// a resolved hostname (e.g. localhost)
// log.info("Calling client address: " + clientAddress.getHostString());
// <hostname>/<ip-address>:<port> format (e.g localhost/127.0.0.1:45136)
// log.info("Calling client address: " + clientAddress.toString());
}
return context.proceed();
} finally {
// After Invocation
}
}
}
Container Interceptor
If you would like to obtain a client IP address before the container provided features like security authentication, you can use the Container Interceptor instead of Java EE EJB Interceptor. See the documentation for details.
The implementation of the container interceptor is the same as the EJB interceptor, but one difference is to define the interceptor as <container-interceptors> in jboss-ejb3.xml instead of @Interceptors annotation (or ejb-jar.xml).
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns:ci ="urn:container-interceptors:1.0">
<jee:assembly-descriptor>
<ci:container-interceptors>
<!-- Default interceptor -->
<jee:interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>com.example.interceptor.ServerSideInterceptor</interceptor-class>
</jee:interceptor-binding>
<!-- Class level container-interceptor -->
<!-- <jee:interceptor-binding> -->
<!-- <ejb-name>ExampleSLSB</ejb-name> -->
<!-- <interceptor-class>com.example.interceptor.ServerSideInterceptor</interceptor-class> -->
<!-- </jee:interceptor-binding> -->
<!-- Method specific container-interceptor -->
<!-- <jee:interceptor-binding> -->
<!-- <ejb-name>ExampleSLSB</ejb-name> -->
<!-- <interceptor-class>com.example.interceptor.ServerSideInterceptor</interceptor-class> -->
<!-- <method> -->
<!-- <method-name>echo</method-name> -->
<!-- </method> -->
<!-- </jee:interceptor-binding> -->
</ci:container-interceptors>
</jee:assembly-descriptor>
</jboss>
Related Infomation
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.