Unified Expression Language, method call list argument - java

i have next method:
public int countEvents(List<EventTypeEnum> eventTypes)
now how to call this method from unified EL ?
With non collection enum arguments works fine but not with collection
Tried
${countEvents("ALERT")}
${countEvents(["ALERT"])}
both crashes

If the values are fixed, you might just do this:
public int countEvents(List<EventTypeEnum> eventTypes) { ... }
public int countAlerts() {
return countEvents(Arrays.asList(EventTypeEnum.ALERT));
}
${countAlerts()}
This is usually the simplest and clearest solution.

Enums could be treated as strings in jstl. But there is no direct way by which you could create a list in jstl. You need to have a list of evenTypes in scope, say ${eventTypes}, which is a List<EventTypeEnum> then you could directly the method in you bean like ${bean.countEvents(eventTypes)}.
However from your code i presume you need to create this on the fly. In that case you'll have to rely on standard jsp. Say you have an enum
public enum EventTypeEnum {
ALERT, ONCLICK, ONBLUR
}
And a pojo which has the count method like
import java.util.List;
public class CountBean {
public int countEvents(List<EventTypeEnum> eventTypes){
return eventTypes.size();
}
}
So if you have an instance of CountBean in scope, say ${myBean} then in you jsp you could do like
<jsp:useBean id="events" class="java.util.ArrayList">
<%
events.add("ALERT");
events.add("ONCLICK");
%>
</jsp:useBean>
Length : <c:out value="${myBean.countEvents(events)}"/>
This would work fine. If you dont want to use <jsp:useBean> approach you could use MicroNova YUZU tags. It is an open-source EL-based JSP tag libary designed to augment JSTL. More details could be found on http://www.micronova.com/yuzu.jsp.
If you dont want to create bean instances to invoke this method and wish to use it as static you could create custom jstl methods as explained here or here.
Hope this helps.

Related

Grails 3 static compilation of taglib

I'm trying to apply #GrailsCompileStatic to taglib and geting the following error:
Error:(19, 16) Groovyc: [Static type checking] - Cannot find matching
method com.tempvs.image.MyTagLib#render(java.util.LinkedHashMap
). Please check if the
declared type is right and if the method exists.
Code example:
#GrailsCompileStatic
class MyTagLib {
...
String myTag = { Map attrs ->
...
out << render(template: '/templates/myTemplate', model: [...])
}
}
What am I doing wrong and how can I solve the problem?
You are using some dynamic features, because taglibs in general do use them. Even just calling "render" is in a sense dynamic.
If you really want to, you can work around this by injecting a PageRenderer and using that to render your page, and then outputting the resulting HTML. I'm not sure it would be worth it, but I certainly don't know your performance requirements!
Example:
import grails.compiler.GrailsCompileStatic
import grails.gsp.PageRenderer
#GrailsCompileStatic
class StaticTestTagLib {
static namespace = "staticTest"
PageRenderer groovyPageRenderer
String myTag = { Map attrs ->
out << groovyPageRenderer.render(template: '/templates/myTemplate', model: [...])
}
}
This works, but you will have some work ahead of you if your taglib is doing anything remotely complex, because EVERY call to render, or any other tag is going to have to be replaced by a statically compiled call. It's possible, but possibly not hugely beneficial.
I am not sure what is the point in creating a new tag that just renders a template.
Grails already has a tag library that renders a template.
<g:render template="displaybook" model="['book':book,'author':author]" />
https://docs.grails.org/latest/ref/Tags/render.html

Is there a way to filter some fields from Play's CRUD form?

I'm using this tag in a custom view, to generate a CRUD form for my object:
<div class="configForm">
#{crud.form /}
</div>
This generate a CRUD form inside my own view. Is there a way to customize the generated form by removing a few fields that I don't want to be editable?
I spotted this line inside form.html:
#{list items:_fields ?: currentType.fields*.name, as:'fieldName'}
If I'm reading this right, then there is a _fields parameter that might let me opt-in to fields (I prefer opt-out, but I'll take opt-in). How do I use this _fields parameter?
You can filter fields like:
#{crud.form fields:['name', 'email', 'password']/}
which will show only the fields name, email and password
Regards
Ronald
I wrote a filtered version of CRUD's ObjectType. The controller can select which fields to filter, like this:
public static void show(long id) {
MyModel object = MyModel.findById(id);
CRUD.ObjectType type = new FilteredObjectType(MyModel.class,
"filteredField1",
"filteredField2");
render(type, object);
}
You can follow Play documentation. Then you can easily write your own ExtCRUD class which ignores all fields which are declared in a static variable of your Controller. How ever FilteredObjectType is for special cases the easier solution.

Spring #ModelAttribute and translating request parameter binding names

I'm working on converting a legacy project to Spring (trying to adjust little as possible for now) and I'm running into a small issue with mapping/translating legacy parameters to a model attribute object. I may be completely wrong in thinking about this problem but it appears to me that to translate a parameter to a specific model attribute setter is to pass in the request parameter through a method for creating a model attribute and manually call the correct setter:
#ModelAttribute("form")
public MyForm createMyForm(#RequestParameter("legacy-param") legacy) {
MyForm myForm = new MyForm();
myForm.setNewParam(legacy);
return myForm;
}
I don't necessarily want to change the request parameter name yet since some javascript and JSPs are depending on it being named that way but is there any way to do something like this? Or is there a different way to map/translate request parameters to model attributes?
public class MyForm {
#ParameterName("legacy-param")
private String newParam;
public void setNewParam(String value) { ... }
public String getNewParam() { ... }
}
#Controller
public class MyController {
#RequestMapping("/a/url")
public String myMethod(#ModelAttribute("form") MyForm myForm, BindingResult result) { ... }
}
The way you've written that model attribute method is indeed odd. I'm not entirely clear what you're actually trying to do.Assuming there are many parameters, you're going to end up with an awful lot of instances of MyForm in your ModelMap. A more 'normal' way to create model attribute would be like this:
#ModelAttribute("legacyParamNotCamel")
public MyForm createMyForm(#RequestParameter("legacy-param-not-camel") String legacy) {
return legacy;
}
Then in the JSP you can refer to it directly in expression language. e.g.,
<c:out value="${legacyParamNotCamel}"/>
If you want to put them onto a form backing object, you need to do it all in a single method that creates the object, not make new copies of it in each method. (assuming your form has more than a single parameter associated with it.)
--
It seems like what you're really trying to do though is translate the parameter names in the request before the web data binder gets ahold of it, so that you can bind oddly named parameters onto a java bean? For that you'll need to use an interceptor that translates the names before the binding process begins, or make your own subclass of the databinder than can take a property name translation map.
You placed the #ModelAttribute at the Method Level but the intention seems to be more of a formBackingObject hence we should be dealing at the Method Parameter Level
There's a difference.
I put up an explanation here on my blog along examples at Spring 3 MVC: Using #ModelAttribute in Your JSPs at http://krams915.blogspot.com/2010/12/spring-3-mvc-using-modelattribute-in.html

JSF: navigation

I have to warn you: the question may be rather silly, but I can't seem to wrap my head around it right now.
I have two managed beans, let's say A and B:
class A
{
private Date d8; // ...getters & setters
public String search()
{
// search by d8
}
}
class B
{
private Date d9; //...getters & setters
public String insert()
{
// insert a new item for date d9
}
}
and then I have two JSP pages, pageA.jsp (the search page) and pageB.jsp (the input page).
What I would like to do is placing a commandbutton in pageB so to open the search page pageA passing the parameter d9 somehow, or navigating to pageA directly after b.insert(). What I would like to do is showing the search result after the insertion.
Maybe it's just that I can't see the clear, simple solution, but I'd like to know what the best practice might be here, also...
I though of these possible solutions:
including **A** in **B** and linking the command button with **b.a.search**
passing **d9** as a **hiddenInput** and adding a new method **searchFromB** in **A** (ugly!)
collapsing the two beans into one
JSF 1.1/1.2 raw doesn't provide an easy way to do this. Seam/Spring both have ways around this and there are a couple of things you can do. JSF 2 should also have solutions to this once it is released.
Probably the easiest and most expedient would be to collapse the two beans into one and make it session scoped. The worry, of course, is that this bean will not get removed and stay in session until the session times out. Yay Memory leaks!
The other solution would be to pass the date on as a GET parameter. For instance, you action method could call the
FacesContext.getCurrentInstance().getExternalContext().redirect("pageB?d9=" + convertDateToLong(d9));
and then get the parameter on the other side.
You should configure the navigation flow in faces-config.xml. In ideal scenario you would return a "status" message which would decide the flow. Read more at following link:
http://www.horstmann.com/corejsf/faces-config.html
http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=/com.businessobjects.integration.eclipse.doc.devtools/developer/JSF_Walkthrough8.html
As far as passing the values from one page to another is concerned you can use backing beans. More about backing beans here:
http://www.netbeans.org/kb/articles/jAstrologer-intro.html
http://www.coderanch.com/t/214065/JSF/java/backing-beans-vs-managed-beans
Hope i have understood and answered correctly to your question
Way to share values between beans
FacesContext facesContext = FacesContext.getCurrentInstance();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, expression, Object.class);
return valueExp.getValue(elContext);
In above code "expression" would be something like #{xyzBean.beanProperty}
Since JSF uses singleton instances, you should be able to access the values from other beans. If you find more details on this technique, I am sure you'll get what you are looking for.
Add commandButton action attribute referencing to B'insert method
<h:commandLink action="#{b.insert}" value="insert"/>
In B'insert method,add d9 parameter as request parameter. Then return an arbitrary string from insert method.
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().put("d9", d9);
Then go to faces context and add navigation from B to A with "from-outcome" as the arbitrary String you returned from insert method. But don't add redirect tag to navigation tags as it will destroy the request coming from B and the parameter you added (d9) will be cleared.
<from-outcome>return string of insert method</from-outcome>
<to-view-id>address of A</to-view-id>
Then you might get the "d9" in A class by fetching it from request map at its constructor or in a place where its more appropriate (getters). You might add it into a session scope or place it to a hidden variable if you want to keep track of it later.
in class A, when page is navigated, A should be initialized as it will be referenced.
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().get("d9", d9);
Sorry i cant give full code, as i have no ide at here, its internet machine at work. I could not give details therefore.
In my opinion, the simplest way is 3-rd option - have both query and insert methods in same class. And you can do something like that:
public String query () {
//...
}
public String Insert() {
//insert
return Query(); }
If your classes are managed Beans you can load class A from class B and call A.query() in your insert method at the end. Also class A can have
<managed-bean-scope>session</managed-bean-scope>
parameter in faces-config.xml and it wouldn't be instantiated again when loaded.

displaytag: suppress zeros in HTML table

I have a HTML table that's generated in a JSP by the displaytag tag library. I would like to suppress any zeros that appear in the table, i.e. they should be replaced by a blank cell. Is there any straightforward way to achieve this?
I discovered that this can be achieved using a custom implementation of ColumnDecorator.
public class SuppressZeroDecorator implements DisplaytagColumnDecorator {
/* (non-Javadoc)
* #see org.displaytag.decorator.DisplaytagColumnDecorator#decorate(java.lang.Object, javax.servlet.jsp.PageContext, org.displaytag.properties.MediaTypeEnum)
*/
public Object decorate(Object rowObject, PageContext pageContext, MediaTypeEnum mediaType) {
if (rowObject != null && rowObject.toString().trim().equals("0")) {
return null;
}
return rowObject;
}
}
The decorator should be declared for each column in the JSP like this:
<display:column property="age" title="Age" decorator="com.example.ZeroColumnDecorator" />
Create a org.displaytag.decorator.TableDecorator instance, and place it into the table. Use the display:table tag's decorator attribute to place your fully qualified decorator class name into the table (I believe you can instantiate one and then place it in, but this class instantiation is trivial...make sure you have a no-arg constructor for this to work properly).
The methods initRow(...) or startRow() are where you would go through your table object, setting any zeroes you find to null (or, if displaying nulls, a blank space). I recommend initRow, but make sure you use super.initRow() first to easily access the current row object. The reason I recommend this is that startRow must return a String (defaults to returning a null string) which I don't think you need to do.
To my knowledge there isn't an "straightforward" way of handling this. The only data-related config property is whether to display nulls or not.
You're better off handling this before the data gets to to the displaytag tag. Perhaps in the servlet that provides the data or a view helper class.

Categories