Karl Kildén
Karl Kildén

Reputation: 2435

Injecting non managed classes with CDI?

I am replacing managed bean declarations in faces-config with CDI (Weld).

Problem is basically this:

project is structured into "web" and "core". Web has the beans that are declared as managed beans. They also have properties declared that are not beans but pojos (?). Core classes are integration classes, domain classes and so on.

I can't name a core class with @Named because it's obviously unfamiliar with the artifacts in the web part of the application.

Today they are specified like this

    <managed-property>
        <property-name>UserData</property-name>
        <value>#{sessionScope.UserData}</value>
    </managed-property>

I am trying to read up on this but would appreciate some help.

How do I inject a managed property that's not a managed bean using CDI (or even JSF2?)

Injecting managed beans into managed beans works flawless and CDI is really kicking as for me so I hope to solve this soon.

Cheers

Upvotes: 2

Views: 4083

Answers (3)

Karl Kild&#233;n
Karl Kild&#233;n

Reputation: 2435

Our application inits these objects at session or application start. All i needed was a producer that get's them from external context and returns them. My solution follows:

Superproducer:

import java.util.Map;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

/**
 * @author Karl Kildén
 *
 * Superclass that should be extended for other producers that uses ext context. 
 */
public class BaseExtContextProducer {

    @Inject
    protected FacesContext facesContext;

    // map used to get UserData objects
    protected Map<String, Object> parameterMap = (Map<String, Object>) facesContext
        .getExternalContext().getSessionMap();

    // variable name i.e "your variable" + message is used for Exception messages
    protected final String message = " may not be null";
}

The actual producer layout that returns my objects:

    import javax.enterprise.context.ApplicationScoped;
    import javax.enterprise.inject.Produces;
    import org.jboss.weld.exceptions.NullInstanceException;

    import com.wmdata.raindance.portal.annotation.qualifiers.FromExtContext;
    import com.wmdata.raindance.portal.tool.UserMessage;

    /**
     * 
     * @author Karl Kildén
     * 
     * This producer gets YourObject that is stored in the external context.
     */


      public class YourObjectProducer extends BaseExtContextProducer {

            @Produces
    //Qualifiers, scopes etc
            @ApplicationScoped @FromExtContext
            public YourObject getYourObject() {
            YourObject yourObject = (YourObject) parameterMap
                .get(YourObject.getStaticName);

            if (YourObject == null) {



// Suggestion: use enum or static name to avoid getting with "" for cleaner code
    throw new NullInstanceException(null,
                YourObject.getStaticName + message);
        }

        return userMessage;
        }
    }

Upvotes: 2

BalusC
BalusC

Reputation: 1108537

As requested by comments, here's how you would do it when using standard JSF annotations.

Given this JSF 1.x managed bean registration:

<managed-bean>
    <managed-bean-name>bean</managed-bean-name>
    <managed-bean-class>com.example.Bean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <property-name>userData</property-name>
        <value>#{sessionScope.userData}</value>
    </managed-property>
</managed-bean>

Here's how the JSF 2.x annotations could be set to get rid of this JSF 1.x style XML registration:

package com.example;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Bean {

    @ManagedProperty("#{sessionScope.userData}")
    private UserData userData;

    // ...
}

Upvotes: 1

Jan Groth
Jan Groth

Reputation: 14636

How do I inject a managed property that's not a managed bean using CDI (or even JSF2?)

If I got your problem correctly, then CDI-Extension is your way to go. What you can do is registering an extension that parses your Non-CDI-Beans at startup time, wraps them as an AnnotatedType and thereby makes them available for injection.

Have a look at Chapter 16 in the Weld documentation, especially 16.6 looks pretty much like your usecase.

And: No worries if "writing own extensions" sounds like hacking the framework. CDI was designed with the extension concept in mind, and registering your own piece of code as an extension is extremely easy and straigthforward.

Upvotes: 2

Related Questions