How to get an EJB client's IP Address information from an EJB applicaiton in JBoss EAP 7.1 or later

Solution Verified - Updated

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:

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>
Components
Category

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.