What is the right approach to process a Freemarker Template on the fly in Spring service bean? - spring

I a few existing freemarker templates (ftl) in Spring MVC project. They are using standard spring tags (#spring.url, #spring.message and #spring.bind). While using standard approach of using FreemarkerConfig inside the servlet context (with ViewResolver) all of the templates work fine.
I also have some email templates which is programatically being created, but they are not using any spring tags or additional tlds.
The twist is, I have a task to use the regular template and process them using Freemarker Template class from a Service Bean. The service class have the find the template in the specified location ("/WEB-INF/views"), but it does not process the spring tags, and finds "spring" variable to null. I have set "auto_import" to "/spring.ftl as spring", but my understanding is it will only work within Web/servlet context? Am I using the right approach here? What is the best way to process a "Template" outside and how to expose the spring.tld or anyother.ltd for it? Appreciate your help / pointers!

Related

Deploying BEAN in OSGi plugin

I am currently deploying my custom controls as OSGi plugins and I wanted to do the same thing with my beans. I have tried putting them into the OSGi plugin and it works fine but the only problem I have is the faces-config.
It seems it has to be called faces-config in the OSGi plugin to work but that means i can't use beans in the NSF anymore because it seems to ignore the local faces-config.
Is there a way to change the name of the faces-config in the OSGi plugin?
Something like FEATURE-faces-config.xml?
In the class in your plugin that extends AbstractXspLibrary, you can override "getFacesConfigFiles", which should return an array of strings representing paths within the plugin to additional files of any name to load as faces-config additions. For example:
#Override
public String[] getFacesConfigFiles() {
return new String[] {
"com/example/config/beans.xml"
};
}
Then you can put the config file in that path within your Java source folder (or another folder that is included in build.properties) and it will be loaded in addition to your app's normal faces-config, beans and all.
The NSFs are running as separate, distinct Java applications. The OSGi plugin is running in the OSGi layer, above all those distinct Java applications, as a single code base. Consequently, the faces-config is only at that level.
It's possible to load them dynamically, by using an ImplicitObjectFactory, loaded from an XspContributor. That's what is done in OpenNTF Domino API for e.g. userScope (which is a bean stored in applicationScope of an NSF). See org.openntf.domino.xsp.helpers.OpenntfDominoImplicitObjectFactory, which is referenced in OpenntfDominoXspContributor, loaded via the extension point of type "com.ibm.xsp.library.Contributor".
A few caveats:
You have no control over what happens if you try to register your bean with a name the developer also uses for a different variable in that scope.
Unless you add code to check if the library is enabled, as we do, you'll be adding the bean to every database on the server.
You still need to add the library to the NSF. Unless you also provide a component that those databases will all use, there's no way you can programmatically add it, as far as I know.
It might be easier to skip the bean approach and just add an instance of the Java class in beforePageLoad, page controller class, or however you're managing the backing to the relevant XPage (if viewScope) or application (if sessionScope / applicationScope).

Spring environment validation

We're building a Spring-based application which will be delivered to end users as a distribution package. Users are responsible for properly configuring whatever needs to be configured (it's mostly about various filesystem locations, folder access permissions, etc). There's a good idea to make the app help users understand what is not configured or which parts of configuration are invalid.
Our current approach is a custom ApplicationContextInitializer which does all the environment validation "manually" and then registers few "low level" beans in the application context explicitly. If something is wrong, initializer throws, exception is caught somewhere in main(), interpreted (converted into plain English) and then displayed.
While this approach works fine, I'm wondering if there are any best practices to minimize hand-written code and use Spring whenever possible.
Here's an illustrative example. The application requires a folder for file uploads. This means:
There should be a configuration file
This file should be accessible by the app
This file should have no syntax errors
This file should explicitly define some specific property (let it be app.uploads.folder)
This property should describe the existing filesystem entity
This entity should be a folder
The app should have read/write access to this folder
Does Spring provide any tools to implement this sort of validation easily?
Spring Boot has a nice feature for context and external configuration validation. If you define a POJO class and declare it as #ConfigurationProperties then Spring will bind the Environment (external properties and System/OS typically) to its properties using a DataBinder. E.g.
#ConfigurationProperties(name="app.uploads")
public class FileUploadProperties {
private File folder;
// getters and setters ommitted
}
will bind to app.uploads.folder and ensure that it is a File. For extra validation you can do it manually in the setter, or you can implement Validator in your FileUploadProperties or you can use JSR-303 annotations on the fields. By default an external property in app.uploads.* that doesn't bind will throw an exception (e.g. a mis-spelled property name, or a conversion/format error).
If you use Spring Boot Autoconfigure #EnableAutoConfigure you don't have to do anything else, but if it's just vanilla Spring (Boot) you need to say #EnableConfigurationProperties in your #Configuration somewhere as well.
A bonus feature: if you also use the Spring Boot Actuator you will also get JMX and HTTP support (in a webapp) for inspecting the bindable and bound properties of #ConfigurationProperties beans. The HTTP endpoint is "/configprops".

Extended Properties for Spring Framework

Looking for a solution that will provide us more functionality within Spring properties such as:
nested structures
maps/lists
properties referencing other properties. Example:
city.name=Toronto
city.address=#{city.name}, 123 Ave SW
I tried EProperties (Google) and Commons Configurations (Apache) but doesn't seem to integrate very well with the Spring Framework.
Also, we're using Velocity to access properties using #springMessage("city.address"), so it needs to work for that.
Does anyone know how I can achieve the above by extending the default Properties capability?
With newest versions of Spring you can use the PropertySource mechanism. You register all your PropertySource and the order in which they are searched and then you don't have to do anything, except perhaps add this to your XML:
<context:property-placeholder />
As long as you declare only one of these without specifying local property files (the "old way"), you will be able to reference property A as the value of property B, even if they are not in the same property source.
For nested structures this may help if you don't like the properties readability:
https://stackoverflow.com/a/13470704/82609
For parsing problems you can easily handle lists and other stuff like that manually very easily:
Reading a List from properties file and load with spring annotation #Value

NamespaceHandler in spring

What is a NamespaceHandler? What is the need to write our custom NamespaceHandler?
Please explain me the significance of NamespaceHandler. Provide me Any links on internet.
It handles specific XML tags found inside a file, such as <log:return />, which is the return tag inside the log namespace.
The best reference is often the Javadoc.
It is useful if you want to use your custom XML tags in an XML configuration:
http://www.theserverside.com/news/1364131/Authoring-Custom-Namespaces-in-Spring-20
If you have a framework and want to add Spring integration to your framework, it could be useful. In that case it would be more important to define the equivalent annotations.

Freemarker Servlet and Struts : access java methods and variables in template

I want to access the Session, Application and Request variables of a Struts web application.
It tells me Session is of type 'HttpSessionHashModel', and looking up the API I saw this class has a method 'isEmpty()'. so I tried for example
<#assign a = Session.isEmpty()>
but it tells me there is no such element 'Session.isEmpty'.
does anyone have an Idea why it is not working?
In Session there are several classes which I could access via
<#assign b = Session["classname"]> (it tells me b is then of type freemarker.ext.beans.StringModel), but I can neither call the methods of class StringModel nor can I get to the objects and methods stored in 'classname'.
hope someone can help
Use the #s macro:
Tags distributed with Struts are automatically made available to FreeMarker templates. To use any tag add "#s." in front of the tag name. Like:
<#s.if test="printName">
<#s.property value="myBeanProperty" />
</#s.if>
References
Using Freemarker Templates - Using Struts tags on FreeMarker templates

Resources