users@glassfish.java.net

[gf-users] Re: Handling env-entry application configuration with Glassfish

From: Laird Nelson <ljnelson_at_gmail.com>
Date: Tue, 22 Jul 2014 10:18:07 -0700

Hi, Lachezar; one thing that perhaps you're getting confused by (as did I,
once) is that the name attribute of @Resource is not a JNDI lookup, but a
logical name of a "slot" into which the configured resource will be
"poured" by the container.

So you referred to it as being a "simplified path": in fact, it's not a
path at all—it's just a name. You could have used "user" instead;
i.e. @Resource(name
= "user").

By doing this, you are saying: "I declare a slot into which I would like a
resource to be poured. The name *of the slot* is 'user'."

Or, if you like, you're declaring a configuration variable whose name is
the value of the @Resource annotation's name attribute. Then in
configuration somewhere, if you're going to target this variable, you're
going to need to refer to it by the same name.

So, in your configuration—in your case, web.xml—you specify (depending on
the resource in question—in this case it's an environment entry you want,
so you're editing <env-entry> stanzas—the name of the slot that should be
filled, and the value to fill it with.

So you would have:

<env-entry>
  <env-entry-name>user</env-entry-name> <!-- equal to @Resource's name
attribute value -->
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>fred</env-entry-value> <!-- or whatever; more on this in
a moment -->
</env-entry>


Please note that in all of this you never had to touch JNDI or be aware of
its existence. A (mostly :-)) sure sign that you're on the wrong track
with configuration is if you start having to type "java:" at the beginning
of a String somewhere. Yes, there are places and times for it, but if
you're using this indirect linkage and staying portable, you won't use it.

(To further illustrate the point: suppose you *did* use "
java:comp/env/config/user" as the value for the @Resource annotation's name
attribute. Then to target this slot in configuration, you would need to
name your <env-entry> java:comp/env/config/user as well:

<env-entry>
  <!-- PLEASE don't do this; it's just a flat name and this is confusing -->
  <env-entry-name>java:comp/env/config/user</env-entry-name> <!-- XXX yuck
-->
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>fred</env-entry-value>
</env-entry>


Remember, this is just a flat name, not a JNDI lookup.)

Exploring further: So what happens when you just do something like this:

@Resource
private String garbage;


...instead of:

@Resource(name = "user")
private String garbage;


...? The answer is that Java EE supplies a value for the name attribute of
that @Resource annotation for you, according to well-specified rules. In
this case, simply using @Resource with no name attribute specified would be
exactly as if you had typed this instead:

@Resource(name = "com.foo.Bar/garbage")
private String garbage;


...that is, the @Resource annotation's name attribute's value will be
exactly equal to the fully qualified class name in which your private
instance variable appears (I'm assuming a class of com.foo.Bar here),
followed by a slash, followed by the name of the variable itself (garbage,
in this dumb example). It's an odd default, but if you stop and think hard
about it, you'll see there probably wasn't a very good alternative.

OK, so back to XML: why do you have to put a value in your web.xml? Is it
really expected that someone somewhere in order to deploy your .war file
properly will have to "crack it open", find the relevant configuration,
edit your <env-entry> stanza by changing (not adding) an <env-entry-value>?
 In every environment that you might deploy your app? Really?!

Yes, unfortunately; that's exactly what is expected. Blame history; in the
earliest days of J2EE (not Java EE), there was apparently a thought that a
huge tool market would spring up around deployment tasks like these, and
that all this editing and cracking open of .wars would be handled silently
by tools. Those tools and the tool market never materialized and here we
are. Stay tuned, though; this area will be improving. :-)

I hope all this helps. I've been in your position many times in the past,
and I know it can be frustrating.

Best,
Laird



On Tue, Jul 22, 2014 at 9:19 AM, Lachezar Dobrev <l.dobrev_at_gmail.com> wrote:

> Using the console I was unable to make it work.
>
> After making your suggested changes:
>
> - Replace @Resource with simplified path
> * this seems to work in the other servers too
>
> - Hard-code env-entry-value in web.xml
>
> The application now deploys.
>
> Digging down I was able to progress one step further:
> bin/asadmin set-web-env-entry ...
> allows changing the environment entries, but:
>
> 1. A hard-coded value in web.xml must be present for this to work
> 2. I could not find a place in the web console to perform this task.
>
> 2014-07-22 15:11 GMT+03:00 Reza Rahman <reza.rahman_at_oracle.com>:
> > Let's kindly start from a working baseline before getting into a
> discussion of what should and should not be.
> >
> > Did my suggested changes work?
> >
> > Sent from my iPhone
> >
> >> On Jul 22, 2014, at 5:37 AM, Lachezar Dobrev <l.dobrev_at_gmail.com>
> wrote:
> >>
> >> 1. Yes, env-entry-value is not filled.
> >> These are configuration parameters, and I do not know what values
> >> they will be assigned at deployment time. Hence the env-entry-value is
> >> missing, and I *expect* them to be filled on deployment using whatever
> >> means the server has. Manually *fixing* the web.xml descriptor in an
> >> already packaged (and possibly cryptographically signed) WAR file is
> >> not my idea of server deployment tools.
> >>
> >> 2. Do I *need* to omit the java:comp/env, or I *can* omit the prefix?
> >> With other J2EE servers I was only able to get it running using the
> >> full java:comp/env/config/user location.
> >>
> >>
> >> I find it hard to believe, that deploying and configuring an
> >> application would require:
> >> a) Hard-coding values by the developer.
> >> b) Manually editing packaged files by hand.
> >>
> >> Am I missing something? Am I supposed to recompile/repackage the WAR
> >> for every instance? Because I can't find a way for this to work
> >> otherwise. I thought I am to provide a WAR file with declared
> >> references to configuration parameters, that are configured/linked
> >> when deploying to the server.
> >>
> >>
> >> After hard-coding some values for the configuration attributes in
> >> web.xml and attempting to deploy the application I got:
> >>
> >>> An error has occurred
> >>> Error occurred during deployment: null. Please see server.log for more
> details.
> >>
> >> And the server.log has:
> >>> [2014-07-22T12:28:03.320+0300] [glassfish 4.0] [INFO] []
> [org.glassfish.admingui] [tid: _ThreadID=122 _ThreadName=admin-listener(9)]
> [timeMillis: 1406021283320] [levelValue: 800] [[
> >>> Exception Occurred :Error occurred during deployment: null. Please
> see server.log for more details.]]
> >>
> >> Which is unhelpful to say the least. I suspect a NPE occurs
> >> somewhere on the server, but the exception is
> >> masked/wrapped/ignored/printed and the actual cause eludes me.
> >>
> >> The same thing happens if I try to deploy the application without
> >> starting it: I get an error message 'null', and then trying to deploy
> >> the application again yields:
> >>
> >>> An error has occurred
> >>> Error occurred during deployment: Application name DemoApplication is
> already in use. Please pick a different name.. Please see server.log for
> more details.
> >>
> >>
> >> 2014-07-21 21:25 GMT+03:00 Reza Rahman <reza.rahman_at_oracle.com>:
> >>> You seem to have two problems:
> >>>
> >>> * env-entry-value is undefined.
> >>> * You simply need @Resource(name = "config/user")
> >>>
> >>>
> >>>> On 7/21/2014 11:53 AM, Lachezar Dobrev wrote:
> >>>>
> >>>> Hello all.
> >>>> I'm having trouble using environment entries to configure an
> >>>> application on deployment in Glassfish.
> >>>>
> >>>> web.xml:
> >>>>
> >>>> <web-app ...>
> >>>> <env-entry>
> >>>> <env-entry-name>config/user</env-entry-name>
> >>>> <env-entry-type>java.lang.String</env-entry-type>
> >>>> </env-entry>
> >>>> </web-app>
> >>>>
> >>>>
> >>>> ServiceProducer.java:
> >>>>
> >>>> @ApplicationScoped
> >>>> public class ServiceProducer {
> >>>> @Produces
> >>>> @Default
> >>>> public Service get() {
> >>>> return new ServiceImpl(user);
> >>>> }
> >>>>
> >>>> private String user;
> >>>> @Resource(name = "java:comp/env/config/user")
> >>>> public void setUser(String user) {
> >>>> this.user = user;
> >>>> }
> >>>> }
> >>>>
> >>>> With "GlassFish Server Open Source Edition 4.0 (build 89)" the
> >>>> ServiceProducer.get() is called before setUser() is called.
> >>>>
> >>>> I'm at a loss here: How can I configure the application?
> >>>>
> >>>> I have added a config/user JNDI Custom Resource:
> >>>> Resource Type: java.lang.String
> >>>> Factory Class:
> >>>> org.glassfish.resources.custom.factory.PrimitivesAndStringFactory
> >>>> Status : Enabled (checked)
> >>>> Properties:
> >>>> name = "value", value = "ConfiguredUserName"
> >>>>
> >>>> Please advise! I'm getting seriously frustrated with this.
> >>>
> >>>
>



-- 
http://about.me/lairdnelson