On 7/2/07, Shiva Kumar H R <shivahr@gmail.com> wrote:
Following the working of NamingBuilders, I have arrived at the following piece of code:

1) Code called from Portlet:
    private static void parseAnnotations(AnnotatedApp annotatedApp, ClassFinder classFinder) throws Exception {
        ResourceAnnotationHelper.processAnnotations(annotatedApp, classFinder, EnvEntryRefProcessor.INSTANCE);
        WebServiceRefAnnotationHelper.processAnnotations(annotatedApp, classFinder);
        HandlerChainAnnotationHelper.processAnnotations (annotatedApp, classFinder);
        ResourceAnnotationHelper.processAnnotations(annotatedApp, classFinder, ServiceRefProcessor.INSTANCE);
        ResourceAnnotationHelper.processAnnotations(annotatedApp, classFinder, AdminObjectRefProcessor.INSTANCE);
        ResourceAnnotationHelper.processAnnotations(annotatedApp, classFinder, ResourceRefProcessor.INSTANCE);
        PersistenceContextAnnotationHelper.processAnnotations(annotatedApp, classFinder);
        PersistenceUnitAnnotationHelper.processAnnotations(annotatedApp, classFinder);
        EJBAnnotationHelper.processAnnotations(annotatedApp, classFinder);
        if (annotatedApp instanceof AnnotatedWebApp) {
            SecurityAnnotationHelper.processAnnotations(((AnnotatedWebApp) annotatedApp).getWebApp(), classFinder);

    private static Module createModule(PortletRequest request, URL moduleUrl) throws Exception {
        Object[] builders = PortletManager.getGBeansImplementing(request, ConfigurationBuilder.class);
        ConfigurationBuilder configurationBuilder = null;
        for (int i = 0; i < builders.length; i++) {
            ObjectName objectName = PortletManager.getNameFor(request, builders[i]).getObjectName();
            if ("EARBuilder".equalsIgnoreCase(objectName.getKeyProperty(NameFactory.J2EE_NAME))) {
                configurationBuilder = (ConfigurationBuilder) builders[i];
        JarFile moduleJar = DeploymentUtil.createJarFile(new File(moduleUrl.toURI()));
        ApplicationInfo applicationInfo = (ApplicationInfo) configurationBuilder.getDeploymentPlan (null, moduleJar, new ModuleIDBuilder());
        Module module = (Module) (applicationInfo.getModules().toArray()[0]);
        return module;

    // function called from Portlet Handler
    public static void parseWarReferences(PortletRequest request, WARConfigData data, URL warUrl)
            throws Exception {
        WebDeployable webDeployable = new WebDeployable(warUrl);

        Module module = createModule(request, warUrl);
        WebAppType webApp = (WebAppType) module.getSpecDD();
        ClassLoader classLoader = webDeployable.getModuleLoader();
        ClassFinder classFinder = null;
        try {
            classFinder = AbstractWebModuleBuilder.createWebAppClassFinder(webApp, classLoader);
            // classFinder = new ClassFinder(webDeployable.getModuleLoader());
        } catch (NoClassDefFoundError e1) {
            // Some of the class types referred in the WAR cannot be resolved.
            // A typical case would be references to EJBs already deployed into the system, and
            // hence not packaged inside WEB-INF/lib directory of WAR.
            // try adding all EJBs deployed in the system as parents of this WAR, and
            // see if referred classes can now be succesfully resolved

            //TODO create a new class loader with deployed-ejbs as parents
            MultiParentClassLoader newClassLoader = null; //TODO
            try {
                classFinder = AbstractWebModuleBuilder.createWebAppClassFinder(webApp, classLoader);
            } catch (NoClassDefFoundError e2) {
        AnnotatedApp annotatedApp = module.getAnnotatedApp();
        parseAnnotations(annotatedApp, classFinder);

        EjbRefType[] ejbRefs = annotatedApp.getEjbRefArray();
        for (int i = 0; i < ejbRefs.length; i++) {
            String refName = ejbRefs[i].getEjbRefName().getStringValue();
            data.getEjbRefs().add(new ReferenceData(refName));

        EjbLocalRefType[] ejbLocalRefs = annotatedApp.getEjbLocalRefArray();
        for (int i = 0; i < ejbLocalRefs.length; i++) {
            String refName = ejbLocalRefs[i].getEjbRefName().getStringValue();
            data.getEjbLocalRefs().add(new ReferenceData(refName));

        ResourceRefType[] resourceRefs = annotatedApp.getResourceRefArray();
        for(int i = 0; i < resourceRefs.length; i++) {
            String refName = resourceRefs[i].getResRefName().getStringValue();
            String refType = resourceRefs[i].getResType().getStringValue();
            if ("javax.sql.DataSource".equalsIgnoreCase(refType)) {
                data.getJdbcPoolRefs().add(new ReferenceData(refName));
            } else if ("javax.jms.ConnectionFactory".equalsIgnoreCase(refType)
                    || "javax.jms.QueueConnectionFactory".equalsIgnoreCase(refType)
                    || " javax.jms.TopicConnectionFactory".equalsIgnoreCase(refType)) {
                data.getJmsConnectionFactoryRefs().add(new ReferenceData(refName));

        ResourceEnvRefType[] resourceEnvRefs = annotatedApp.getResourceEnvRefArray();
        for(int i = 0; i < resourceEnvRefs.length; i++) {
            String refName = resourceEnvRefs[i].getResourceEnvRefName().getStringValue();
            ReferenceData refData = new ReferenceData(refName);
        if(annotatedApp instanceof AnnotatedWebApp) {
            MessageDestinationType[] messageDestinations = ((AnnotatedWebApp)annotatedApp).getWebApp().getMessageDestinationArray();
            for(int i = 0; i < messageDestinations.length; i++) {
                String refName = messageDestinations[i].getMessageDestinationName().getStringValue();
                ReferenceData refData = new ReferenceData(refName);

2) Changes required to AdminObjectRefBuilder and AbstractWebModuleBuilder:
<please see attached file AdminObjectRefBuilder.patch>

With my limited set of test WARs, I observe that although this code works for @Resource annotations (references to JMS Connection Factories, JMS Destinations and JDBC Connection Pools), it fails for @EJB annotations as explained below.

Please suggest if above code would be acceptable. Suggestions/Hints of doing it better is welcome. I suspect there might be better ways of creating 'Module' object (with a proper EARContext, yet not deploying it in the system) and 'ClassFinder' objects.

Here is one failure scenario for EJB references:
Input WAR has a Servelt that references an EJB as below:
    @EJB(name = "ejb/Converter")
    private Converter converter;
The referenced EJB ('Converter') is already deployed in the system.

When function "parseWarReferences()" above is called for this WAR, it would fail at
"classFinder = AbstractWebModuleBuilder.createWebAppClassFinder (webApp, classLoader);"
with a ClassNotFoundError for "Converter" EJB.

Following is the solution I can think of:
Try adding all EJBs deployed in the system as dependencies of this WAR (temporarily), and see if referred classes can now be succesfully resolved while creating ClassFinder object.

The question then would be "given the pattern name for an EJB JAR (like 'default/CurrencyConverterEJB/1.0/jar' how do I obtain a reference to this deployed EJB-JAR's classloader? " Any hints will be helpful.

Found a way for doing this :)

    private static List getConfigClassLoaders(List configurationNames) {
        List classLoaders = new ArrayList();
        ConfigurationManager configurationManager = PortletManager.getConfigurationManager();
        for (int i = 0; i < configurationNames.size(); i++) {
            Artifact configurationId = Artifact.create((String) configurationNames.get(i));
        return classLoaders;
Will now work on handling Web Service References and Security Settings in a WAR.


On 6/27/07, Shiva Kumar H R <shivahr@gmail.com > wrote:
Thanks David. Will look into the working of NamingBuilders.

- Shiva

On 6/26/07, David Jencks < david_jencks@yahoo.com > wrote:

On Jun 26, 2007, at 8:13 AM, Shiva Kumar H R wrote:

This is with regard to auto generation of Geronimo deployment plans ( http://issues.apache.org/jira/browse/GERONIMO-3254). One problem where I am currently stuck is in the discovery of Annotations.

User input to my wizard/portlet would be the Java EE module (WAR/EJB-JAR/EAR) and output would be the Geronimo deployment plan. An important step in this process is to discover all references declared in the Java EE module and then ask the user to resolve them ( http://issues.apache.org/jira/secure/attachment/12360303/3ResolveReferences.gif ).

References declared in the spec deployment descriptor (web.xml/ejb-jar.xml) can easily be discovered by parsing the spec DD (lines 921 to 959 of http://issues.apache.org/jira/secure/attachment/12360289/PoC.patch). References declared as Annotations in java code (with probably no mention in the spec DD) is what is posing the problem now.

Are there any standard APIs that simplify the job of discovering these Annotations (and optionally get them into the spec DD)? Please note that this must be achieved without the need for actually deploying the Java EE module onto the server (user is in the process of still creating the Geronimo deployment plan using wizard/portlet).

Any help and hints is greatly appreciated.

roughly the first thing the NamingBuilders do is find all the relevant annotations and modify the spec dd by adding xml with the same meaning (when not already overridden).  I recommend you figure out how this works and use the NamingBuilders to do this.  You might need to expose another method on the naming builders for your portlet to call.  

david jencks