You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Bryan Hunt <ad...@revoltingdigits.com> on 2004/07/07 20:01:19 UTC

using Constants from JSTL .....

Ok, tearing my hair out right now and extremely confused.

If you look at the Java Technology Forums you will see a rather nice 
little pattern that
someone called evnafets has created, it allows you to use a single 
Constants class
both in your Actions and in your JSP pages ...

It uses reflection to add it's static final members to a map which can 
then be accessed by JSTL like so
<c:out value="${Constants.FOR_RENTAL_PROPERTIES_SELECTION}"/>

The address is 
http://forum.java.sun.com/thread.jsp?forum=45&thread=508847&message=2415101 
<http://forum.java.sun.com/thread.jsp?forum=45&thread=508847&message=2415101>

This works with a lot of stuff but the jstl and struts tags seem to be a 
little inconsistent in their behaviors.

For example this works ...

snip=
<html:select property="propertyTypes" multiple="true">
            <html-el:optionsCollection 
name="${Constants.PROPERTY_TYPES_SET}" value="id" label="name"/>
         </html:select>
=snip

But for some reason ( my stupidity and the time of the evening ) I 
cannot get this to work.
snip=
<c:set var="emailNotifications" 
value="${scope['Constants.EMAIL_NOTIFICATIONS']"></c:set>
<c:out value="${emailNotifications.priceRangeStart}"/>
=snip

or like this

snip=
<c:set var="emailNotifications" 
value="${scope[${Constants.EMAIL_NOTIFICATIONS}]"></c:set>
<c:out value="${emailNotifications.priceRangeStart}"/>
=snip

I'm starting to feel like I'm back in my Perl days again .... Is there a 
way that I can dereference these
beans or do I have to use sloppy string literals in my jstl code ?

Any suggestions or am I just stupid to want to do this ?

--b






---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Kris Schneider <kr...@dotech.com>.
It's not so bad, really ;-). For some additional background, here are a few
older messages from struts-user and taglibs-user:

http://marc.theaimsgroup.com/?l=struts-user&m=103790677413408&w=2
http://marc.theaimsgroup.com/?l=struts-user&m=105777660215673&w=2
http://marc.theaimsgroup.com/?l=taglibs-user&m=105889207116316&w=2

Here's a slightly different approach:

package com.dotech.util;

import java.io.Serializable;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ConstantBean implements Serializable {

    private Map constants;

    public ConstantBean() {
        super();
    }

    public void setClassName(String className) throws ClassNotFoundException,
                                                      IllegalAccessException {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader == null) {
            loader = getClass().getClassLoader();
            if (loader == null) {
                loader = ClassLoader.getSystemClassLoader();
            }
        }
        Class clazz = loader.loadClass(className);
        Field[] allFields = clazz.getDeclaredFields();
        int numFields = allFields.length;
        Map propMap = new HashMap(numFields);
        for (int i = 0; i < numFields; i++) {
            Field f = allFields[i];
            int mods = f.getModifiers();
            if (Modifier.isPublic(mods) &&
                Modifier.isStatic(mods) &&
                Modifier.isFinal(mods)) {
                String name = f.getName();
                Object value = f.get(null);
                propMap.put(name, value);
            }
        }
        this.constants =  Collections.unmodifiableMap(propMap);
    }

    public Map getConstants() {
        return this.constants;
    }
}

Which can be used in a page like this:

<%@ page contentType="text/plain" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<jsp:useBean id="responseConstants" class="com.dotech.util.ConstantBean">
    <jsp:setProperty name="responseConstants"
                     property="className"
                     value="javax.servlet.http.HttpServletResponse"/>
</jsp:useBean>

SC_INTERNAL_SERVER_ERROR: <c:out
value="${responseConstants.constants.SC_INTERNAL_SERVER_ERROR}"/>

Quoting Bryan Hunt <ad...@revoltingdigits.com>:

> Uh oh, I just realised that is the exact same as mine just implimented 
> differently.
> 
> <c:out value="${CONSTANTS.WHATEVER)"/>
> 
> Will output the string value but will not be able to be used to resolve 
> the bean by that
> name.
> 
> I'm giving up on JSTL constants.  Nice idea ... but too expensive on my 
> hairline.
> 
> --b
> 
> Rick Reumann wrote:
> 
> > On Wed, 07 Jul 2004 20:12:02 +0200, Bryan Hunt 
> > <ad...@revoltingdigits.com>  wrote:
> >
> >> And it works fine, but really what I am trying to get here is the 
> >> value  of using Constants in
> >> both my Actions and my ( JSTL based ) jsp's.
> >
> >
> > You need to have all your Constants in a Map that is in application 
> > scope.  Kris Schneider posted this great piece of code to add to your 
> > Constants  file to return all your constants as a Map. At app start up 
> > I have a  servlet that does several things, one of which call the 
> > properties method  to put all the stuff in a Map and then you can just 
> > put that in scope:
> >
> >
> > //in some servlet at startup:
> > ServletContext context = contextEvent.getServletContext();
> > context.setAttribute("CONSTANTS", UIConstants.getConstantsMap());
> >
> >
> > (Below you don't need to do like I have. I had other reasons to do it 
> > this  way at the time. But just provide the getConstantFieldsAsMap() 
> > method )
> >
> > //example class: UIConstants
> >
> > private static Map constantsMap;
> > static {
> >     constantsMap = getConstantFieldsAsMap(UIConstants.class);
> > }
> >
> > public static Map getConstantsMap() {
> >     return constantsMap;
> > }
> >
> > //all your constants:
> > public final static String WHATEVER = "whatever";
> >
> > //this does the work.. thanks Kris
> > private static Map getConstantFieldsAsMap(Class cls) {
> >     Map propMap = null;
> >     try {
> >         Field[] allFields = cls.getDeclaredFields();
> >         int numFields = allFields.length;
> >         propMap = new HashMap(numFields);
> >         for(int i = 0; i < numFields; i++) {
> >             Field f = allFields[i];
> >             int mods = f.getModifiers();
> >             if(Modifier.isPublic(mods) && Modifier.isStatic(mods) &&  
> > Modifier.isFinal(mods)) {
> >                 String name = f.getName();
> >                 Object value = f.get(null);
> >                 log.debug("Putting name = " + name + " and value=" + 
> > value  + " into propMap");
> >                 propMap.put(name, value);
> >             }
> >         }
> >     } catch(IllegalAccessException ie) {
> >         log.error("Problem loading constantFieldsAsMap " + ie);
> >     }
> >     return Collections.unmodifiableMap(propMap);
> > }
> >
> > //end class
> >
> >
> > Now in JSP you can just do:
> >
> > <c:out value="${CONSTANTS.WHATEVER)"/>

-- 
Kris Schneider <ma...@dotech.com>
D.O.Tech       <http://www.dotech.com/>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Bryan Hunt <ad...@revoltingdigits.com>.
Uh oh, I just realised that is the exact same as mine just implimented 
differently.

<c:out value="${CONSTANTS.WHATEVER)"/>

Will output the string value but will not be able to be used to resolve 
the bean by that
name.

I'm giving up on JSTL constants.  Nice idea ... but too expensive on my 
hairline.

--b

Rick Reumann wrote:

> On Wed, 07 Jul 2004 20:12:02 +0200, Bryan Hunt 
> <ad...@revoltingdigits.com>  wrote:
>
>> And it works fine, but really what I am trying to get here is the 
>> value  of using Constants in
>> both my Actions and my ( JSTL based ) jsp's.
>
>
> You need to have all your Constants in a Map that is in application 
> scope.  Kris Schneider posted this great piece of code to add to your 
> Constants  file to return all your constants as a Map. At app start up 
> I have a  servlet that does several things, one of which call the 
> properties method  to put all the stuff in a Map and then you can just 
> put that in scope:
>
>
> //in some servlet at startup:
> ServletContext context = contextEvent.getServletContext();
> context.setAttribute("CONSTANTS", UIConstants.getConstantsMap());
>
>
> (Below you don't need to do like I have. I had other reasons to do it 
> this  way at the time. But just provide the getConstantFieldsAsMap() 
> method )
>
> //example class: UIConstants
>
> private static Map constantsMap;
> static {
>     constantsMap = getConstantFieldsAsMap(UIConstants.class);
> }
>
> public static Map getConstantsMap() {
>     return constantsMap;
> }
>
> //all your constants:
> public final static String WHATEVER = "whatever";
>
> //this does the work.. thanks Kris
> private static Map getConstantFieldsAsMap(Class cls) {
>     Map propMap = null;
>     try {
>         Field[] allFields = cls.getDeclaredFields();
>         int numFields = allFields.length;
>         propMap = new HashMap(numFields);
>         for(int i = 0; i < numFields; i++) {
>             Field f = allFields[i];
>             int mods = f.getModifiers();
>             if(Modifier.isPublic(mods) && Modifier.isStatic(mods) &&  
> Modifier.isFinal(mods)) {
>                 String name = f.getName();
>                 Object value = f.get(null);
>                 log.debug("Putting name = " + name + " and value=" + 
> value  + " into propMap");
>                 propMap.put(name, value);
>             }
>         }
>     } catch(IllegalAccessException ie) {
>         log.error("Problem loading constantFieldsAsMap " + ie);
>     }
>     return Collections.unmodifiableMap(propMap);
> }
>
> //end class
>
>
> Now in JSP you can just do:
>
> <c:out value="${CONSTANTS.WHATEVER)"/>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Rick Reumann <st...@reumann.net>.
On Wed, 07 Jul 2004 20:12:02 +0200, Bryan Hunt <ad...@revoltingdigits.com>  
wrote:

> And it works fine, but really what I am trying to get here is the value  
> of using Constants in
> both my Actions and my ( JSTL based ) jsp's.

You need to have all your Constants in a Map that is in application scope.  
Kris Schneider posted this great piece of code to add to your Constants  
file to return all your constants as a Map. At app start up I have a  
servlet that does several things, one of which call the properties method  
to put all the stuff in a Map and then you can just put that in scope:


//in some servlet at startup:
ServletContext context = contextEvent.getServletContext();
context.setAttribute("CONSTANTS", UIConstants.getConstantsMap());


(Below you don't need to do like I have. I had other reasons to do it this  
way at the time. But just provide the getConstantFieldsAsMap() method )

//example class: UIConstants

private static Map constantsMap;
static {
     constantsMap = getConstantFieldsAsMap(UIConstants.class);
}

public static Map getConstantsMap() {
     return constantsMap;
}

//all your constants:
public final static String WHATEVER = "whatever";

//this does the work.. thanks Kris
private static Map getConstantFieldsAsMap(Class cls) {
     Map propMap = null;
     try {
         Field[] allFields = cls.getDeclaredFields();
         int numFields = allFields.length;
         propMap = new HashMap(numFields);
         for(int i = 0; i < numFields; i++) {
             Field f = allFields[i];
             int mods = f.getModifiers();
             if(Modifier.isPublic(mods) && Modifier.isStatic(mods) &&  
Modifier.isFinal(mods)) {
                 String name = f.getName();
                 Object value = f.get(null);
                 log.debug("Putting name = " + name + " and value=" + value  
+ " into propMap");
                 propMap.put(name, value);
             }
         }
     } catch(IllegalAccessException ie) {
         log.error("Problem loading constantFieldsAsMap " + ie);
     }
     return Collections.unmodifiableMap(propMap);
}

//end class


Now in JSP you can just do:

<c:out value="${CONSTANTS.WHATEVER)"/>

-- 
Rick

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Rick Reumann <st...@reumann.net>.
On Thu, 08 Jul 2004 09:43:11 -0400, Rick Reumann <st...@reumann.net>  
wrote:

> <c:set var="emailNotifications"  
> value="${servletContext[Constants.EMAIL_NOTIFICATIONS]}"/>

Duh, my bad, as David mentioned the above should be ${applicationScope..  
}. Sorry about that.

-- 
Rick

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Rick Reumann <st...@reumann.net>.
On Thu, 08 Jul 2004 13:49:11 +0200, Bryan Hunt <ad...@revoltingdigits.com>  
wrote:

> <c:set var="emailNotifications"  
> value="${scope[${Constants.EMAIL_NOTIFICATIONS}]}"></c:set>

Actually I haven't seen the 'scope' property like that, but have you tried  
(assuming ApplicationScope)...

<c:set var="emailNotifications"  
value="${servletContext[Constants.EMAIL_NOTIFICATIONS]}"/>

The above should work assuming you have a Constants class that is in  
Application scope and Constants is either a Map (with a key  
EMAIL_NOTFICATIONS) or a regular bean with a getEMAIL_NOTIFICATIONS method  
in it.

-- 
Rick

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Bryan Hunt <ad...@revoltingdigits.com>.
Hmmm, that gives me no error but no result either  I put in the 
following code to test it and just got blank
screen.
snip=
<jsp:useBean id="Constants" class="ie.jestate.web.Constants"/>
<c:set var="emailNotifications" 
value="${scope[${Constants.EMAIL_NOTIFICATIONS}]}"></c:set>
<c:out value="${emailNotifications}"/>
<c:out value="${emailNotifications.priceRangeStart}"/>
<c:out value="${emailNotifications.priceRangeEnd}"/>
<c:forEach items="${emailNotifications.urbanAreas}" var="urbanArea">
    <c:out value="${urbanArea.name}"/>
</c:forEach>
=snip

If I substitute the following line instead it works fine.
<c:set var="emailNotifications" value="${EMAIL_NOTIFICATIONS}"></c:set>

This line of code ...
<c:out value="${Constants.EMAIL_NOTIFICATIONS}"/>

Outputs
EMAIL_NOTIFICATIONS
on the screen.

I think this is starting to look like it just isn't going to work, I 
don't think that jstl is too smart about dynamic
variables like this. I tried the other suggestion as well (

c:set var="const" value="${scope['Constants']}"/>
<c:set var="emailNotifications" value="${const['EMAIL_NOTIFICATIONS']}"/>
)

But it didn't work either, this is starting to look as though it will be 
so convoluted that I might as well not be trying to use constants anyhow 
as I will have to look up the file anyway I might as well just use 
string literals. 

Cause it isn't scriptlet I wont get auto-completion anyhow. I'm going 
to try the suggestion from Rick Reumann and then I'm gonna throw my 
computer out the window.

--b





Denis Avdic wrote:

>Have you tried 
><c:set var="emailNotifications" value="${scope[Constants.EMAIL_NOTIFICATIONS]"/>
>?
>
>On Wed, 07 Jul 2004 20:12:02 +0200, Bryan Hunt
><ad...@revoltingdigits.com> wrote:
>  
>
>>Just as an addition I can do this
>>
>><jsp:useBean id="Constants" class="ie.jestate.web.Constants"/>
>>
>><c:set var="emailNotifications" value="${EMAIL_NOTIFICATIONS}"></c:set>
>>
>><c:out value="${emailNotifications.priceRangeStart}"/>
>><c:out value="${emailNotifications.priceRangeEnd}"/>
>><c:forEach items="${emailNotifications.urbanAreas}" var="urbanArea">
>>   <c:out value="${urbanArea.name}"/>
>></c:forEach>
>>
>>And it works fine, but really what I am trying to get here is the value
>>of using Constants in
>>both my Actions and my ( JSTL based ) jsp's.
>>
>>Perhaps this is just something that never occured to the writers of the
>>JSTL spec ?
>>
>>--b
>>
>>
>>
>>
>>Bryan Hunt wrote:
>>
>>    
>>
>>>Ok, tearing my hair out right now and extremely confused.
>>>
>>>If you look at the Java Technology Forums you will see a rather nice
>>>little pattern that
>>>someone called evnafets has created, it allows you to use a single
>>>Constants class
>>>both in your Actions and in your JSP pages ...
>>>
>>>It uses reflection to add it's static final members to a map which can
>>>then be accessed by JSTL lik
>>>      
>>>
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>>For additional commands, e-mail: user-help@struts.apache.org
>>
>>
>>    
>>
>
>  
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: using Constants from JSTL .....

Posted by Bryan Hunt <ad...@revoltingdigits.com>.
Just as an addition I can do this

<jsp:useBean id="Constants" class="ie.jestate.web.Constants"/>

<c:set var="emailNotifications" value="${EMAIL_NOTIFICATIONS}"></c:set>

<c:out value="${emailNotifications.priceRangeStart}"/>
<c:out value="${emailNotifications.priceRangeEnd}"/>
<c:forEach items="${emailNotifications.urbanAreas}" var="urbanArea">
    <c:out value="${urbanArea.name}"/>
</c:forEach>

And it works fine, but really what I am trying to get here is the value 
of using Constants in
both my Actions and my ( JSTL based ) jsp's.

Perhaps this is just something that never occured to the writers of the 
JSTL spec ?

--b



Bryan Hunt wrote:

> Ok, tearing my hair out right now and extremely confused.
>
> If you look at the Java Technology Forums you will see a rather nice 
> little pattern that
> someone called evnafets has created, it allows you to use a single 
> Constants class
> both in your Actions and in your JSP pages ...
>
> It uses reflection to add it's static final members to a map which can 
> then be accessed by JSTL lik


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org