struts to spring migration message resources - java

I am converting an application from struts 1 to Spring MVC and I am trying to figure out what to do in my Java code when its using the import org.apache.struts.config.MessageResourcesConfig and org.apache.struts.util.MessageResources. In the spring-servlet.xml file I added the line to include my message resources properties file but I am not longer going to use the struts 1 libraries. How would I go about the conversion of this part of the code?
It is used a good bit throughout the application such as places like this:
this.config = new MessageResourcesConfig();
this.config.setParameter("path that was used here was set in the spring-servlet configuration file");
this.resources = MessageResources.getMessageResources(this.config.getParameter());

I would refactored the way you load the Resources using java.util.ResourceBundle
// load resourcebundle.properties
bundle = ResourceBundle.getBundle("resourcebundle");
You can then get a value using
String val = bundle.getString(key);
You can have an helper class to get the values you need, and/or find a way to pass it to the JSP (cannot help you there, sorry)

Related

SpringBoot 2.7.5 - #Value annotation not assigning any values from application.properties file

I am using Spring Boot 2.7.5
While using #Value annotation to inject values form application.properties file, getting null assignment to variables under #Configuration class.
Example:
#Value("${file.name}")
private String fileName;
Here I am getting seeing assignment to variable fileName
Ideally it should assign value '${file.name}' if key isn't matching. But null assignment means something is breaking in the project (at least I think so, I need experts comments on this).
Same thing is working in another project but not in this particular.
Let me know if my question is not elaborative enough and will try to explain in detail
My question is, why is it working in other project but not in this one. What configurations could go wrong which I need to check. Have gone through multiple stackoverflow solutions and verified all below:
application.properties file spell check
#Configuration annotation at top of class where #Value is being used
key value pair assignment and spell check of all keys
no issues with library imports
Tried to add #PropertySource("classpath:foo.properties")
import org.springframework.beans.factory.annotation.Value;
resources folder is correctly marked as 'Resources Root'
Temporary Alternative
private Properties props = new Properties();
props.load(VaultCredential.class.getResourceAsStream("/application.properties"));
props.getProperty("file.name");
Can you please try with below code
private String PathForImageGallery;
#Value("${file.name}")
public void PathForImageGallery(String PathForImageGallery) {
this.PathForImageGallery = PathForImageGallery;
}
Apologies everyone. I was calling a class where was trying to bind #Value with properties and calling it in main() method of #SpringBootApplication.
Totally missed that main() method will not load property values until spring application is up and running.
Working solution if some one want to load properties before even running a SpringBoot application -
private Properties props = new Properties();
props.load(VaultCredential.class.getResourceAsStream("/application.properties"));
props.getProperty("file.name");
PS - Thanks all for your efforts. Admins can close it down if considered as non-logical question.

Configuring global list of allowed classes for serialization

I am using Inifinispan v12.1 with String Boot v2.5.2 via org.infinispan:infinispan-spring-boot-starter-embedded. In our application we are using custom classes which we would like to cache (very common case), however it turned out that starting from v10 these classes need to be listed in "allow list".
We are using infinispan.xml configuration passed via infinispan.embedded.config-xml property as advised by sample project.
Question: How is it possible to configure allow list globally for all caches by the means of XML configuration file?
I have considered the following options:
System property infinispan.deserialization.allowlist.regexps (from ClassAllowList) – not good choice as configuration will be spread between XML file and e.g. some other place. More over if the property is renamed in future Infinispan versions one would notice it only when application is run.
Defining the <cache-container><serialization><allow-list> as to documentation is not good option because will result several identical per-cache XML configuration blocks.
The corresponding Java Config for Spring Boot application would be:
#org.springframework.context.annotation.Configuration
public class InfinispanConfiguration {
#Bean
public InfinispanGlobalConfigurationCustomizer globalCustomizer() {
return builder -> builder.allowList().addRegexp("^org\\.mycompany\\.");
}
}
P.S. Javadoc in GlobalConfiguration assumes that there is <default> XML section the configuration can be read from, but in fact XML does not support it anymore.
P.P.S. Arguably the dots in the packages should be escaped in SpringEmbeddedModule and start with ^ because ClassAllowList uses Matcher#find() (boolean regexMatch = compiled.stream().anyMatch(p -> p.matcher(className).find());):
serializationAllowList.addRegexps("^java\\.util\\..*", "^org\\.springframework\\..*");

Java: ServletContext equivalent in Plain Java

I have the following servlet code to store a data for a specific reason and later I retrieve the same data in another scenario in a project. It works fine as expected.
// setting
ServletContext context = request.getSession().getServletContext();
context.setAttribute("imageData", data);
// retrieving ...
ServletContext context = request.getSession().getServletContext();
byte[] data = (byte[])context.getAttribute("imageData");
Now, In an another project, where I use plain java program, where I want to store data similar to this servlet logic. I tried using the same code in plan java project, but it throws error, not accepting this servletcontext in plan java file.
Could someone please help, 1.) what is the equivalent in plan java to store like this temporarily or 2.) How to make that servletconext code working in plain java ?
Thank you in advance!
Getsy
How about simple HashMap<String, Object>
You can consider using simply a HashMap in the applet context.
If you need to use the same code in applet and web contexts, add a layer of abstraction and two implementations to manage the attributes depending on the context.

Add Freemarker support to customized JSP tag

I have a customized JSP tag library with a Java class (extending TagSupport) that generates the output for my web application. It has some parameters that are formed into HTML code using a StringBuilder.
Now the generated HTML is becoming more complex and hard to handle with calls of StringBuilder.append, so I'd like to replace the code generation with a Freemarker template.
I already found out that I could use a generic Struts component tag instead, because the Struts tags already use Freemarker template files, so I could write a tag like:
<s:component template="/components/myStruct.ftl">
<s:param name="myParam" value="%{'myParam'}" />
</s:component>
Then writing the specified template file myStruct.ftl would probably solve my problem. I actually did not try if Struts really finds and uses that file correctly, but I optimistically expect it to work.
My question is, if it's also possible to retain the current code with the customized tag
<my:struct param="myParam" />
and only change the Java class linked to that tag.
I've found code that reads a Freemarker template:
Configuration config = FreemarkerManager.getInstance().getConfiguration(pageContext.getServletContext());
config.setServletContextForTemplateLoading(pageContext.getServletContext(), "/components");
Template templ = config.getTemplate("myStruct.ftl");
templ.process(params, pageContext.getOut());
but it seems very circuitously to me and I wondered what would be the "standard" way to do it. Additionally it seemed that you cannot use tags from the Struts tag library in a template used like this. (I ran into an ArrayIndexOutOfBoundException, caused by Sitemesh... I did not analyze it yet.)
My intention was to keep the Java class as some kind of wrapper around the Struts component tag. Maybe somthing like:
OgnlValueStack stack = TagUtils.getStack(pageContext);
Component c = new Component(stack);
c.addParameter("param", param);
But I don't know how to continue this code stub. It may be crap anyway.
Is there an easy/"standard" way to do this or do I simply have to get rid of the customized tag?
Thanks in advance.
A friend of mine sent me this link:
http://cppoon.wordpress.com/2013/02/27/how-to-create-a-struts-2-component-with-freemarker/
This is what I was looking for. The gist is to change the customized tag to not extend TagSupportbut AbstractUITag which makes it a Struts tag instead of a JSP tag, roughly speaking.
This enables the automatic linkage (by name and path conventions) to my Freemarker template. I basically followed the instructions on that page. I only added the methods that are abstract in the super class, so they had to be implemented.
IMO the site lacks of a description of how the UI bean class is linked to the tag class. But as the IDE forces you to implement the getBean method inside the tag class, you quickly get to this code (using the classes described on that site):
#Override
public Component getBean(OgnlValueStack stack, HttpServletRequest request, HttpServletResponse response)
{
Pagination pagination = new Pagination(stack, request, response);
pagination.setList(list);
return pagination;
}
This might not be completely correct for the recent Struts, but it worked for the ancient version I've got to use.
Thanks again to the guy who sent me the link :)

In Grails, how can I get a ConfigObject of messages.properties for locale?

In Grails, I would like to get a ConfigObject reference to the loaded messages properties file for the current locale. Or some way to easily read in the messages properties (for the current locale) in it's entirety. I want to convert it to JSON and send it back to the client to be used to lookup strings via javascript.
In essence I want to do something like this:
def props = new java.util.Properties()
props.load(... the right message bundle ...);
def messages = new ConfigSlurper().parse(props)
render messages as JSON
I'm assuming there's a more graceful way to do this. The messageSource interface only allows you to get a message for a particular key. I want the entire resource bundle so I can convert it to JSON.
I found a workable solution of just loading the properties directly from the proper messages properties bundle based on the current locale.
It looks like I can just load the file with a path relative to the root of the application. This worked for running locally both with the embedded tomcat and as a war ('grails run-app' and 'grails run-war') but I haven't tested deployed to a container to know if the path will be resolved properly.
Here's my test controller:
import grails.converters.*
import org.springframework.context.i18n.LocaleContextHolder as LCH
class I18nController {
def index = {
def locale = LCH.getLocale().toString();
def langSuffix = ( locale == "en" ) ? "" : "_${locale}"
def props = new java.util.Properties()
props.load( new FileInputStream( "grails-app/i18n/messages${langSuffix}.properties" ) )
render ( new ConfigSlurper().parse(props) ) as JSON
}
}
Can be accessed like:
http://localhost:8080/myapp/i18n
http://localhost:8080/myapp/i18n?lang=es
http://localhost:8080/myapp/i18n?lang=en
I know this is old, but I came here looking to do the exact same thing. Using LocaleContextHolder to get the desired locale is a good starting point, although I decided to use RequestContextUtils. In my implementation, I wanted to use java's own locale resolution strategy. So here goes (currently using grails 2.1.2):
// Controller
import org.springframework.web.servlet.support.RequestContextUtils
import grails.converters.JSON
class I18nController {
def strings() {
ResourceBundle clientMessages = ResourceBundle.getBundle("com.example.ClientMessages",
RequestContextUtils.getLocale(request),
Thread.currentThread().contextClassLoader)
render clientMessages as JSON
}
}
When you serialize this thing using the default JSON marshaller, it's not what you want. So add this to your BootStrap.groovy inside the init closure:
// JSON Marshaller to serialize ResourceBundle to string table.
JSON.registerObjectMarshaller(ResourceBundle) { bundle ->
def returnObject = [:]
bundle.keys.each {
returnObject."${it}" = bundle.getString(it)
}
returnObject
}
And finally, put the resources you want to send to the javascript client side in your classpath. In my example, these would go in src/java/com/example/ClientMessages.properties.
size.small=Small
size.wide=Wide
size.large=Large
In the client, going to myapp/i18n/strings you will see the JSON like this:
{"size.small":"Small","size.wide":"Wide","size.large":"Large"}
So with this solution, you put all and only the strings you want to send to the javascript side for lookup, and put everything else in the grails i18n folder. One caveat is that the strings here are not available to g:message and vice versa. If anyone can figure out a solution to single out one basename in i18n for this purpose, I'd like to see it.
The implementation type of MessageSource is org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource. Perhaps there are methods on this class (or one of it's parents), that will allow you to get a reference to the entire set of Properties.
The following looks like it might work (though I haven't tested it):
// Get a reference to the message Source either via dependency injection or looking-up
// the bean in the application context
def messageSource
Properties messages = messageSource.getProperties("messages.properties").properties
// Now convert the Properties instance to JSON using your favorite Java-JSON library
This is not a great solution as the getProperties(filename) method is protected, so you should not be able to call it, but you can because of a bug in Groovy. It also makes some implicit assumptions about the implementation type of mesageSource.

Categories