On May 6, 2012, at 4:48 AM, Mark Struberg wrote:
>
>
> David, exactly this doesn't work out in practice!
>
> look at jboss5 datasource xml as an example:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <datasources>
> <local-tx-datasource>
> <jndi-name>myDS</jndi-name>
>
> <connection-url>jdbc:postgresql://someserver:5432/someDb</connection-url>
> <user-name>user</user-name>
> <password>pwd</password>
> <driver-class>org.postgresql.Driver</driver-class>
>
> </local-tx-datasource>
> </datasources>
>
> This will create the following JNDI location in JBossAS5: java:/myDS
>
> NO comp, NO lang, NO other qualifier.
That's because you didn't declare the reference using the portable mechanisms I
described: via @Resource annotation on a field, method or class of a component,
or <resource-ref> in the web.xml.
Step 1 is to chose a name and declare it via standard means and use only that
name in your app.
Step 2 is to use the vendor specific means to link that name to the target
environment.
Doing it any other way is every bit as non-portable as you say.
Yes, Step 2 is vendor specific, you really can't avoid that (well actually you
can, more on that later), but what it does is get the vendor specific out of
your code. It's pretty easy to put mapping files for several vendors in their
app.
For OpenEJB/TomEE there usually is no Step 2 required and just declaring the
reference and creating a datasource is enough.
As of JavaEE 6 you can skip Step 2 portably via declaring the datasource via
the new @DataSourceDefinition.
I recall your app and I'd guess the heart of your distaste is that you
essentially configure two datasources and then pick one at runtime.
In static code, this is possible (there is equivalent xml):
@DataSourceDefinition(name = "java:app/test/ds" ....)
@DataSourceDefinition(name = "java:app/prod/ds" ....)
@Resource(name = "java:app/ds", lookup="java:app/prod/ds")
public class SomeCdiBean {
}
Two datasources are declared and one symlink that the application can use
safely. Clearly the above "symlink" is still hardcoded, so to get some more
dynamic behavior you could potentially put the "@Resource" link on a separate
class in a separate jar. Perhaps a "prod.jar" to hold all the mappings for
production and a "test.jar" to hold all the mappings for test, then make sure
only one of them is in the application at any given time.
Still limited of course as changing the archive is required and often that
isn't allowed between test and production.
There are several ways CDI could help with this that haven't been directly
addressed and are not tested, so not likely to work now, but definitely
something we should address. The ideas are too cool to ignore.
Q1. Alternatives and JavaEE Resource annotations. What happens if a CDI bean
is annotated with "@Resource(name = "java:app/ds", lookup="java:app/prod/ds")",
but has an alternate annotated with "@Resource(name = "java:app/ds",
lookup="java:app/test/ds")?
One would hope that either the main bean's JNDI entries *or* the alternate
bean's JNDI entries will go into effect, not both. This isn't explicitly
covered so I doubt will work. Something we might want to add at the spec level.
Q2. Extensions adding/removing beans. What happens if a CDI bean is annotated
with "@Resource(name = "java:app/ds", lookup="java:app/prod/ds")" and is vetoed
by an Extension?
One would hope that the JNDI entries that would be added by the vetoed bean are
also essentially vetoed and the bean does not have an impact on the JNDI
namespace. Also not explicitly addressed and something we might want to tackle
at the spec level.
-David