Access resource bundle outside struts action class - struts2

There are several ways to handle resource bundle using Struts 2.3 framework. This includes using certain UI tags in the View class or getText() method in your Action class.
However, there is no straight-forward mechanism to access this resource bundle in a java class or any other class except View and Action.
I found two ways to access it in a java class,however, they fail to completely replace the old MessageResources of Struts 1.2 framework.
Following are the two ways with drawback of each
Using ResourceBundle class of java.util package.
Locale locale = (Locale)request.getSession().getAttribute(ConstantsFnl.LOCALE_KEY);
ResourceBundle rb = ResourceBundle.getBundle(bundle,locale);
message = rb.getString(key);
The drawback with this approach is you cannot pass an array of arguments which can be replaced in your message text.This functionality was present in Struts 1.2 with MessageReosurces.
Using DefaultTextProvider of Struts 2.3 framework.
DefaultTextProvider dtp = new DefaultTextProvider();
return dtp.getText(key, (String[])params);
Though this approach gives you a way to pass an array of arguments to be replaced in your message text, it does not give you a mechanism to specify the locale or specify the bundle to be searched.Again,this functionality is present in Struts 1.2 with MessageResources class.
Looking for an optimum approach.Any help on this would be great.

You can use methods found in:
com.opensymphony.xwork2.util.LocalizedTextUtil

Related

Calling a static method from Thymeleaf TEXT template - how to bypass the Restricted mode

Is it possible to call a static method from a Thymeleaf textual template?
Official guide mentions that it should be possible to call a method like this:
<p th:text="${#myapp.translator.Translator#translateToFrench(textVar)}">Some text here...</p>
When I try to use it in my textual template (TemplateResolver's mode is set to TemplateMode.TEXT), I get a this exception:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating OGNL expression: "#java.lang.System#currentTimeMillis()" (template: "template.txt" - line 1, col 18)
Here is my sample template:
System millis: [(${#java.lang.System#currentTimeMillis()})]
After googling for a while, I also found this form of calling methods:
System millis: [(${T(java.lang.System).currentTimeMillis()})]
which fails with the same error.
What I need to do is somehow allow usage of a custom number formatter class from a template (functionality of the #numbers utility object is not rich enough for my case).
I can call methods on a non-static class by providing it as a context variable like this:
Some value: [(${formatter.format(someValue)})]
but it would be easier for me to use a static class without a need to explicitly adding it to each template's context.
BTW, I do not use Spring, just pure Thymeleaf.
Update
I should've spend more time to analyze the stack trace of the Thymeleaf exception I got.
It turns out, that the root cause of this behavior was the org.thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes is forbidden in this context exception, which is results from this change: https://github.com/thymeleaf/thymeleaf/issues/809
Downgrading to Thymeleaf 3.0.11 "fixes" it.
Now I'm looking for a solution to bypass this new Resctricted mode on the latest Thymeleaf (3.0.12 for the moment). I'm sure it's safe in my case, because I'm the only author of both code and templates.
An alternative would be to use the th:with attribute. It's a little more verbose, but still should allow you the same flexibility. (This works for me on 3.0.12.RELEASE.)
[# th:with="time=${#java.lang.System#currentTimeMillis()}"]System millis: [[${time}]][/]
https://github.com/thymeleaf/thymeleaf/issues/816#issuecomment-826401631 has extensive info on why this was done and possible workarounds. In your case, it will be best to add a model attribute in your controller and use that instead of calling the static method in the template.
#Controller
public class MyController {
public String myControllerMethod(Model model) {
model.addAttribute("time", System.currentTimeMillis());
return "name-of-the-thymeleaf-template";
}
}
and update your template to use:
System millis: [(${time})]

Modify the token returned by Struts2 s:token tag

In a Struts 2 webapp (which also uses Spring),
I want to modify the "output" of the <s:token> tag to use my own token-generation algorithm.
It appears the <s:token> tag is handled by a class called org.apache.struts2.components.Token, which is a UIBean. Is there a standard way using either Struts or Spring by which I can "extend" or "modify" or replace the Token class, or the methods it uses to generate tokens?
Alternatively, can I make up my own <mytoken> tag that works in Struts 2?
At the moment in the latest S2 version 2.3.20 there is no simple way of doing that. The TokenHelper class which is responsible for generating tokens is a simple utility class with static methods.
You are better off using your own custom token solution. You need an interceptor which will handle tokens and something that will put token into JSP. For that you can create custom tag or just use a hidden input which calls some method in your base action.
Note: The execAndWait interceptor uses TokenHelper too, so if you are using execAndWait you need to change it as well.

Where do a Grails controller's "expando" methods come from?

According to the documentation, a Grails controller is simply a class with "Controller" appended to the name and saved in grails-app/controllers/. The simplest of such a class being:
package some.package
class FooController {
def index = {}
}
When the Grails application is run, this controller will inherit some standard methods like getParams and getSession. From the attached screenshot I can see that these are added via groovy.lang.ExpandoMetaClass. What I don't see is how this happens. The controller doesn't implement any interfaces or extend any abstractions. Where do these methods come from?
From Grails 2.0 a new methodology was adapted to add the dynamic methods to the controller artefacts. You can visit them step wise to see how those properties are added to Controllers:-
Controller in grails is not part of grails-core but a plugin by itself to grails named grails-plugin-controllers.
Being a plugin, the corresponding *GrailsPlugin Class would define the behavior of the plugin.
ControllersApi (extending CommonWebApi) bears all those properties which are to added to controller artefact. (Introduced from Grails 2.0)
ControllerGrailsPlugin registers ControllersApi as a spring bean.
There is more to just adding ControllerApi as a bean.
There is a concept of MetaClassEnhancer which would take/consider an API (in this case ControllerApi) and enhance/reconcile the artefact (controller) with the corresponding API by adding CachedMethods to the artefact using reflection, which is the role of a BaseApiProvider present in grails-core.
This magic happens in the Controller plugin class as well.
Now, prior to Grails 2.0 a different method was adapted to add the dynamic properties to controller. That way metaClass properties were added to controllers at runtime which was found to be less efficient. Each of the dynamic property was represented by its own class (viz: GetParamsDynamicProperty, GetSessionDynamicProperty) which is not in use right now.
So what you need to look now in the object tree for those dynamic methods is this where the CachedMethods are available in the controller. Hope that helps. I would be glad to add more if you seek more. :-)
You are right, Grails 'Controllers' are not really Controllers in the sense they inherit from a base class, but rather they are just simple POGOs that follow the convention of being placed in the grails-app/controllers directory. When your application is compiled, 30+ methods are mixed in through AST transformations, the majority of them coming from
org.codehaus.groovy.grails.plugins.web.api.ControllersApi, but also from
org.codehaus.groovy.grails.plugins.converters.api.ConvertersControllersApi,
org.codehaus.groovy.grails.plugins.web.api.ControllersMimeTypesApi.
The preceding was paraphrased from Programming Grails by Burt Beckwith, and I would recommend it if you are interested in the finer details of Grails.
Quoting from Burt Beckwith's excellent book, Programming Grails:
Over 30 methods are mixed into controller classes with AST
transformations. The majority are added from the
org.codehaus.groovy.grails.plugins.web.api.ControllersApi class
ControllersApi source

when should we have Portlet-class to have an predefined class and a custom class

This is my Portlet.xml inside the existing project .
Could anybody please tell me when should we have Portlet-class to have an predefined class and a custom class ??
<portlet>
<portlet-name>DataUpload</portlet-name>
<display-name>DataUpload</display-name>
<portlet-class>org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher</portlet-class>
<init-param>
<name>viewNamespace</name>
<value>/view</value>
</init-param>
</portlet>
<portlet>
<portlet-name>Reports</portlet-name>
<display-name>Reports</display-name>
<portlet-class>com.tata.ReportAction</portlet-class>
</portlet>
This is an ample question and hard to answer in its full sense. However, there are some rules that are almost always followed:
If your portlet does use some Java framework (like Struts 2, JSF) it will almost certainly use a predefined javax.portlet.GenericPortlet subclass. All the processing is made by the framework and the portlet class has the sole purpose of redirecting the requests to the framework. This kind of portlet class is called bridge. In your example, your bridge is org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher.
If your portlet does use the Liferay MVC portlet and only show retrieved data in JSPs (without updating them), then you may not need to write your custom portlet class. You may not need another class because the com.liferay.util.bridges.mvc .MVCPortlet class does present JSPs automatically. I will not explain it in detail, but that is the point. This is a rare situation, so do not think much about it.
If your portlet does not use Liferay MVC but instead is written in plain JSR 286 API, then you will probably need to write your custom portlet class. It is because the default render(), doView() etc. methods of GenericPortlet are not enough to present JSPs.
If your portlet does not use any Java generic framework, uses Liferay MVC and does process data by updating it, then you will probably need some custom subclass of MVCPortlet. This is so because the processing of data is made by methods called during the action phase. These methods (usually called "process action methods") are recognized by having two parameters of the types javax.portlet .ActionRequest and javax.portlet .ActionResponse.
In your example, you have two portlets: one which uses Struts (so the portlet class just dispatches requests to Struts 2) and another one which uses a custom portlet class. This portlet class can either extend GenericPortlet or MVCPortlet. If it uses GenericPortlet, then it is inevitable to have a custom class. If it does use MVCPortlet, then this class probably has some process action methods.
I bet my answer is way too abstract, but I hope it gives you some ideas about other questions, more specific and answerable.

Good way to introduce constant string to i18n internationalization file in grails

In grails, is there a way in the i18n file to reference a constant value. I'm trying to do something like this:
constant.sitename=Fancy SiteName
intro.headline.label=Welcome to {constant.sitename}
home.headline=You're at {constant.sitename}
The reason is I don't want to change the sitename in every single string if we decide to change the name, I only want to do it once. Is there a way to accomplish this requirement?
I realize I could also set a constant in the Config.groovy, but then that would require passing in the param on every single message that required it, which I'd rather not have to do this as it would make developers lives worse.
You might override Grails' standard messageSource bean by a custom implementation in resources.groovy. By default the Grails i18n plugin uses PluginAwareResourceBundleMessageSource for this.
So, subclass this and override the necessary code to add property replacement. Don't know by heart what exact methods these are, but that should be easy to figure out with a debugger.

Resources