geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Shiva Kumar H R" <shiv...@gmail.com>
Subject Re: Stuck in discovering Annotations - Please Help!
Date Mon, 02 Jul 2007 16:22:05 GMT
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];
                break;
            }
        }
        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) {
                return;
            }
        }
        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);
            refData.setRefLink(refName);
            data.getJmsDestinationRefs().add(refData);
        }
        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);
                refData.setRefLink(refName);
                data.getMessageDestinations().add(refData);
            }
        }
    }

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.

Thanks,
Shiva

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.
> >
> > thanks
> > david jencks
> >
> >
> > Thanks,
> > Shiva
> >
> >
> >
>

Mime
View raw message