using <set> tag in grails - grails

I am new to grails. I came across a set tag which we can use in gsp pages itself to set the values which is similar to setting model from the controller.
<g:set var="home" value="something" />
so that when we write ${home} it outputs "something".
Is there any way to set the value in sessions in gsp pages itself and not from controller using set tag?

Yes you can do it in gsp pages as well. You just have to include an extra attribute scope to indicate which scopes(session, flash, page and request) you are setting the value to.
<g:set var="home" value="something" scope="session" />
If you do not include the scope option then it defaults to page.
To display the the value you just have to write ${session.home} or ${request.home} or simply ${home} for request scope. Hope this helps.
For more : https://grails.github.io/grails-doc/3.0.x/ref/Tags/set.html

Well! above answer suffices the need. Just wanted to add one more thing that gsp pages comprises of jsp internally and hence all the 9 implict objects are available on gsp pages as well.
request HttpServletRequest object
response HttpServletResponse object
out PrintWriter object used to send output to the client.
session HttpSession object
application ServletContext object associated with application context.
config ServletConfig object associated with the page.
pageContext server-specific features JspWriters.
page synonym for this
Exception handling exceptions and error page redirects.An instance of javax.servlet.jsp.JspException
You could at any point of time access these in your gsp pages.
More you can read from this.
Hope it helps!

Related

Open a new tab don't create new ViewAccessScoped bean

I have a sample use case: I have an edit page that use GET parameter "id".
eg. edit?id=1
This edit page is backed by a ViewAccessScoped (CODI) Bean.
In this edit page, I have a datatable with links that link to the same "edit" page, but with another id. (eg. edit?id=2)
<h:link value="#{mecaPart.id}" outcome="edit" target="_blank">
<f:param name="id" value="#{mecaPart.id}" />
</h:link>
The problem, is that the window open correctly, but it is the same bean that is used! And so I am editing the same part...
I have placed a log in #PostConstruct, and it is the same bean reference that is called multiple times. (even with the new ID!)
My question, how can I tell JSF to create a new ViewAccessScoped backing bean when I click the link, and not re-use the actually used one?
Finally, I discovered that #ViewScoped CODI bean did not preserved the backing bean from page refresh. So, I have to use ViewAccessScoped.
According to Gerhard Petracek: http://os890.blogspot.fr/2011/08/scopes-view-scope-vs-view-access-scope.html
the view-scope of jsf2+ is bound to a concrete jsf page. that means: as soon as you navigate to a different page, the state gets lost. that's better than nothing, but not useful for a lot of use-cases. the main use-case which needs it are ajax-requests on a page and the data used by them aren't needed on other pages, but it's pretty easy to break it e.g. with a browser-refresh on a page which stores the data in a view-scoped bean and has no form with input components. (in a previous blog post i described how to use the infrastructure provided by codi to create a session based view-scope to overcome such disadvantages cause by storing view scoped beans as part of the tree-state.)
like with the view-scope view-access-scoped beans are available on a page, but they also exist for the next page. that means: they are forwarded to the next page and get destroyed autom. if they don't get used during the first request of the next page. that's e.g. useful for wizards. if you have a wizard page which doesn't use the bean or you have to support the possibility to interrupt a wizard, you can use the grouped-conversation scope (and even the window-scope) provided by codi. however, due to the powerful api of codi you can also destroy the scope manually at any time (if needed).
So, to solve the problem of opening a new tab with another "ID", I had to set "CODI Client Side WindowHandler", according to the CODI Wiki.
https://cwiki.apache.org/confluence/display/EXTCDI/JSF+WindowHandler
So I added:
<alternatives>
<class>org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.ClientSideWindowHandler</class>
</alternatives>
To the file beans.xml, and I used #ViewAccessScoped. Everything is working smoothly now.
You can use #ViewScoped which also works in CODI

Difference in navigation by action="xyz" and action="#{bean.returnXyz}"

How is navigation from a Facelet page
<p:commandLink action="xyz.xhtml">
or a backing bean
<p:commandLink action="#{bean.redirect}">
public class Bean{
public String redirect(){
.....
return "xyz.xhtml";
}
}
different from each other?
How is navigation from a xhtml page or a backing bean different from each other.
There's no difference. The both examples invoke a POST request and instructs JSF to render the view associated with the given outcome. The backing bean method has the only advantage that it allows you to perform some business logic beforehand or even control the outcome value programmatically.
However, if you don't have any business logic at all and solely want to have an idempotent link to another page, then using a command link is actually a bad practice. Using POST for page-to-page navigation is not user nor SEO friendly. The target page is not bookmarkable (the URL remains the one of the page where the POST form was been submitted to) nor searchbot-crawlable (it is using JavaScript to submit a hidden form).
You should instead use a normal link.
<h:link outcome="xyz.xhtml">
This generates a SEO-friendly <a> element with the full URL in its href and ends up in an user-friendly bookmarkable URL.
See also:
When should I use h:outputLink instead of h:commandLink?
How to navigate in JSF? How to make URL reflect current page (and not previous one)
Check out the documentation of p:commandLink here, which says the following for action attribute:
A method expression or a string outcome to process when command is
executed.
Now, as action="xyz.xhtml" returns String xyz.xhtml you're redirected accordingly and for action="#{bean.redirect}" which again returns xyz.xhtml you are again redirected according to the returned String.

CDI bean List in datatable is null on submit from JSF

Please note: This question is about CDI scopes as we are using CDI scopes in the app and not JSF scopes.
1) Controller Bean (TestController.java) which is in RequestScoped (enterprise context) is called index_cut.xhtml, when we come for first time on this page.
2) On button “Load”, we load the following method to populate the sapFinancialPeriodList which works fine and displays the data
3) After changing the content on the page and submitting, the sapFinancialPeriodList appears as NULL in the following method –
Any suggestions?
Your bean is request scoped and you're loading the data model on action only instead of on (post)construction. When the HTTP response after the action which loaded the data is finished, then the bean is garbaged. The subsequent request would get a brand new instance of the bean with all properties set to default. However, as the same data model isn't been preserved during (post)construct, it remains empty.
In JSF2 you'd solve this with using #ViewScoped. This way the bean will live as long as you're interacting with the same view by postbacks (which return null or void).
In CDI you'd need to solve this using #ConversationScoped, which in turn requires some additional #Inject Conversation boilerplate, complete with begin() and end() calls at the right moments. For a concrete example, see also What scope to use in JSF 2.0 for Wizard pattern?.
An alternative is to pass the parameters responsible for creating the data model to the subsequent request via <f:param> in the command link/button as follows
<h:commandButton value="save" ...>
<f:param name="period" value="#{bean.period}" />
</h:commandButton>
and then recreate exactly the same data model in (post)constructor of the request scoped bean as follows
String period = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("period");
List<SapFinancialPeriod> sapFinancialPeriodList = someservice.list(period);
(the above is by the way nicer to solve with #ManagedProperty if you were using standard JSF; as far as I know CDI doesn't have an annotation which enables you to set a HTTP request parameter as a bean property)
See also:
How to choose the right bean scope?
Unrelated to the concrete problem, the upcoming JSF 2.2 solves this functional requirement in a nicer way using the new "Faces Flow" feature with the new #FlowScoped annotation and the new xmlns:j="http://java.sun.com/jsf/flow" tags.

How do I set Managed Bean field to the value of a ui:param?

I have a JSF page that is included in other JSF pages (basically a page header, with common information). This common page has its own controller and is reliant that the page which includes this common page pass it some common data.
Specifically, I am currently trying to include this common page on other pages using:
<ui:include src="commonPage.xhtml">
<ui:param name="commonData" value="#{thisPagesController.commonData}"/>
</ui:include>
Which should pass "commonData" to the commonPage.xhtml page and ideally set the "commonData" property on the CommonPageController class:
#ManagedProperty("#{commonData}")
CommonData commonData;
However, this is not working... the managed property is not getting set.
What is the proper way to do this?
See comment from BalusC. There is no standard for this in the JSF API spec. Use a composite or custom component instead.

viewParam and the request scoped bean

I tried to use view parameters in conjunction with a request scoped bean. I noticed that the model does get updated and when the page is rendered, the bean properties are set and are rendered with <h:outputText value="myBean.myParameter />. My question is, about the post back. I was under the impression that the view parameter values were retained as long as you don't post to a different view. I expected that the property would be set in the bean during the action method call automatically, but in practice I found this is not the case. Can someone explain why this is the case. I searched all around and I found many articles discussing viewParams but I couldn't find an explanation of exactly what the effect is (and why) in each scope. If anyone knows of an article that documents this already can you point me to it. Thanks in advance...
I was under the impression that the view parameter values were retained as long as you don't post to a different view.
This is only true when you're using a view scoped bean because they are remembered in the bean. The view scoped bean lives as long as you're interacting with the same view. I think that you're confusing the request scope with the view scope, given your impression.
A request scoped bean is trashed by end of the HTTP request/response cycle. So when the webbrowser is finished loading the page, the request scoped backing bean is already trashed for long. When you submit a form on that page, a new request scoped bean will be created, the <f:viewParam> will check if the to-be-set request parameters are available and if not, then just skip it (or validate; if you have required="true" set on them). As long as you don't retain view parameters by using <f:param> inside command links/buttons of the form on that page, then those parameters will get lost on subsequent requests and thus also in any involved request scoped bean.
See also:
Communication in JSF 2.0

Resources