Rishabh Agarwal
Rishabh Agarwal

Reputation: 2172

EJB counterpart of Spring @Profile

Spring Profiles provide a way to segregate parts of an application configuration and make it be available only in certain environments. Wanted to know whether this can be done in EJB also in any way?

Main Problem statement:

I have two different JMS infrastructure in two different environments. I want the corresponding bean to be loaded and injected.

Upvotes: 2

Views: 1161

Answers (2)

Mehran Mastcheshmi
Mehran Mastcheshmi

Reputation: 815

You could use CDI alternatives and use @Inject instead of @EJB for injection Examples: 1)if you need to specify implementation at deployment time you can use alternative

interface :

import javax.ejb.Local;

@Local
public interface MyserviceInterface2 {
    String doSomthing();
}

implementations

@Alternative
@Stateless
public class Interface2Impl1 implements MyserviceInterface2{
    @Override
    public String doSomthing() {
        return "Impl1";
    }
}


@Alternative
@Stateless
public class Interface2Impl2 implements MyserviceInterface2{
    @Override
    public String doSomthing() {
        return "Impl2";
    }
}

select your implementation in beans.xml

<alternatives>
    <class> [your package].Interface2Impl1</class>
</alternatives>

Injection point:

inject in client class

public class ClientClass {
    @Inject
    MyserviceInterface2 myserviceInterface2;
    ...

2)if you want to select implementation in runtime, you could use produces

create following qualifires

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Impl1Qulifier {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Impl2Qulifier {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface SelectedImpQulifier {
}

interface:

@Local
public interface MyServiceInterface {
    String doSomthing();
}

implementations :

@Impl1Qulifier
@Stateless
public class MyServiceImpl1 implements MyServiceInterface{
    @Override
    public String doSomthing() {
        return "Impl1";
    }
}

@Impl2Qulifier
@Stateless
public class MyServiceImpl2 implements MyServiceInterface{
    @Override
    public String doSomthing() {
        return "impl2";
    }
}

produces:

public class ImplProvider {
    @Inject @Impl1Qulifier
    MyServiceInterface impl1;

    @Inject @Impl2Qulifier
    MyServiceInterface imp2;

    @Produces @SelectedImpQulifier
    MyServiceInterface createServiceInterface(InjectionPoint injectionPoint ) {
//        if( your conditions ){
//            return impl1
//        }
        return imp2;
    }
}

injection point:

public class ClientClass {
    @Inject @SelectedImpQulifier
    MyServiceInterface myServiceInterface;
    ...

you also could use JNDI lookup for second situation

You also could put each implementation in different module(jar) and use the proper one for each environment in ear that is created for that environment (doing proper assembling for each of them)

Upvotes: 2

JGlass
JGlass

Reputation: 1467

Using env-entry's in your EJB project for environment configuration

Example ejb-jar.xml (this is placed in the "META-INF" folder)

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd" version="3.2">
<display-name>MSInterceptorMDBSimpleOrderHandler </display-name>

<enterprise-beans>
<message-driven>
    <ejb-name>InterceptorMDBSimpleOrderHandler</ejb-name>
    <transaction-type>Container</transaction-type>

    <env-entry>
        <description>Variables to distinguish between prod, uat and qa environments</description>
        <env-entry-name>isQA</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>false</env-entry-value>
    </env-entry>

    <env-entry>
        <description>Variables to distinguish between prod, uat and qa environments</description>
        <env-entry-name>isUAT</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>false</env-entry-value>
    </env-entry>

    <!-- Not QA or UAT means it's prod -->

    <env-entry>
        <description>Variable to distinguish between linux and windows for file access</description>
        <env-entry-name>isLinux</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>true</env-entry-value>
    </env-entry>

    <env-entry>
        <description>Variable to use as linux folder path file access</description>
        <env-entry-name>linuxPath</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>/home/jboss/XML_JMS_Responses</env-entry-value>
    </env-entry>

    <env-entry>
        <description>Variable to use as windows folder path file access</description>
        <env-entry-name>windowsPath</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>C:\\local_git_repo\\PSD_Interceptor\\XML_JMS_Responses</env-entry-value>
    </env-entry>        
</message-driven>


Example code (note, this is a MDB):

@MessageDriven
public class InterceptorMDBSimpleOrderHandler implements MessageListener {
        @Resource(name="isQA")
        boolean isQA;
        @Resource(name="isUAT")
        boolean isUAT;
        @Resource(name="isLinux")
        boolean isLinux;
        @Resource(name="linuxPath")
        String linuxPath;
        @Resource(name="windowsPath")
        String windowsPath;

        //other vars modified by resource injected values
        String path = "";
        boolean isWindows = false;
        boolean isProd = false;

        @PostConstruct
        public void initialize() {
            LOGGER.info("InterceptorMDBSimpleOrderHandler:->PostConstruct:->initialize");

            if(!isQA && !isUAT){
                isProd = true;
            }

            if(!isLinux){
                isWindows = true;
                path = windowsPath;
            }else{
                path = linuxPath;
            }

            LOGGER.info("InterceptorMDBSimpleOrderHandler Constructed with following settings:");
            LOGGER.info("isQA: " + isQA);
            LOGGER.info("isUAT: " + isUAT);
            LOGGER.info("isProd: " + isProd);
            LOGGER.info("isLinux: " + isLinux);
            LOGGER.info("isWindows: " + isWindows);
            LOGGER.info("linuxPath: " + linuxPath);
            LOGGER.info("windowsPath: " + windowsPath);
            LOGGER.info("Path to use: " + path);

            //this is where you'd call a method or whatever that cares 
            //about the environment settings.

            LOGGER.info("InterceptorMDBSimpleOrderHandler:->PostConstruct:->Finish initialized");
        }

}



It doesnt need to be a message driven bean, it can be just a EJB in which case you'd change "message-driven" to "session" in the ejb-jar.xml as such:

<enterprise-beans>
<session>
  <ejb-name>Configuration</ejb-name>
  <init-on-startup>true</init-on-startup>
  <transaction-type>Container</transaction-type>

The above is a snippet from an EJB class called "Configuration" which holds a whole bunch of env-entries related to configuration for the app.
For more information ENC Usage Conventions Environment_Entries it's a little old but 80% or more still holds true.

Upvotes: 1

Related Questions