Can I pass an Object variable from FTL file using the Request using methods like setAttribute/setParameter to the Servlet?
There is no clear documentation of how to use FTL with Servlet's when I want to post a request from FTL to a servlet.
My FTL file needs to be submitted to a Servlet, to which I need to pass data.
I am getting data into the FTL file from the previous Servlet, but I am stuck at how to send it to the next servlet.
Each of these servlet's are responsible to certain functionality.
Templates meant to be used as MVC View only, so in theory you should not do things like that in them. I mean manipulating Servlet-specific stuff directly, or anything that's not a presentation concern. If your architecture needs something like invoking other servlets on a way that <#include_page .../> can't do, wrap that into a custom directive or custom method (TemplateDirectoveModel and TemplateMethodModel interfaces) which conveys the high-level meaning when you look at the template, and hides the gory technical details inside the Java implementation, where you can do whatever you want, as it's Java. Looking at the implementation of include_page is possibly a good starting point. You can drop the new directive or method into the data-model, or into the Configuration as shared variable, or pull it inside an #import-ed/#include-ed common template with <#assign myDirective = 'com.example.MyDirective'?new()>.
Related
Suppose I have a certain operation that should be available to every process running in Spring MVC.
Say string normalization--
i need to run a method that normalizes the string fields before doing anything else on that form/data.
One thing specific to do is, to normalize the String fields on every input form before
they are dispatched to the back-end services. Likewise, that operation (normalization)
should be run on data from the back-end before it is dispatched to the view component.
One way of doing this that I can think of is:
Code a bean doing it-- the normalization. Then, define this bean somewhere at the top in
the context hierarchy of Spring-- ApplicationContext.xml or WebApplicationContext.xml(?),
so that it will be visible and can be used
accross all the processes/servlets in the application.
Then, Whenever and from wherever needed, invoke that method on the bean defined up there.
Or, inject it to the relevant fields in the bean definitions(?)
In this case, is there a way to call it before or during a HandlerMapping is running? if so, how?
Another i can come up with is:
Code a validator (implement Validator) to run that process and "validate" the String fields for you.
But i dont see how this would be of good help.
From what i know, a validator runs on specific object types. I can define that type generically(?)
but then I'm operating on the fields-- not objects as a whole each.
Coding validator(s) seems too costly to me for this use-- even if it is an option here.
I'm new to Spring. pls bear with me on this.
I've got a HashMap as Map<Long, List<Map<String, Object>>> typeAndKno, in the FreeMarker page, I get the content of this map like this:
<#list typeAndKno?keys as typeId>
${typeAndKno.get(typeId).get(0).get('TYPE_NAME')}
<#list typeAndKno.get(typeId) as kno>
${kno.get('KNOWLEDGE_ID')}
</#list>
</#list>
This code works fine in Struts2, but after moved to Spring MVC, the code fails. I finally changed the code to this:
<#list typeAndKno?keys as typeId>
${typeAndKno[typeId]?first['TYPE_NAME']}
<#list typeAndKno[typeId?string] as kno>
${kno['KNOWLEDGE_ID']}
</#list>
</#list>
What's the difference between these two pieces of code? Is there a way to make the first piece of code work in Spring MVC?
Update:
As of 2.3.22 there's a much easier and non-disruptive solution for this: configure FreeMarker so that ?api works, and then you can use the Java API of Map where the keys aren't String-s. See this FAQ entry or this answer for more details.
And Strut's FreeMarker setup is something that's strongly discouraged now. Of course, back then, when they did that, that was maybe the most reasonable workaround, but it isn't anymore for a while, and especially not since 2.3.22.
Old answer (outdated):
The way you see Java objects from templates depends on the ObjectWrapper used, which is a FreeMarker configuration setting. Based on your example, Struts uses a BeansWrapper with its default settings, while Spring possibly uses the DefaultObjectWrapper. So that causes the differences. I wouldn't recommend using either, because:
With BeansWrapper with its default settings Map keys mix with the method names, with method names having priority. Surely you can safely use myMap.get(key) to get around that, but myMap.get('foo') is just horrible compared to myMap.foo, which will only work as far you have no method called foo. Also ?keys will return a mixture of real keys and method names with it... it's a mess.
With DefaultObjectWrapper you can safely write myMap.foo, but you won't be able to get entities with non-string keys, because myMap[key] only support strings, and you don't have myMag.get(key) anymore.
So what I have usually used with FreeMarker was a bw = new BeansWrapper(); bw.setSimpleMapWrapper(true). With this, the methods of Map-s are not visible, just like with DefaultObjectWrapper, so you can use myMap.foo and myMap[key] safely. But if rarely you need to get something with a non-string key, you can use myMap(nonStringKey) (yes, with () instead of []). This last doesn't work with DefaultObjectWrapper. (Hopefully FreeMarker 2.4 will solve this mess with non-string keys nonsense, but it's not like it will be out anytime soon...)
So the next question is how to set the object wrapper with Spring. I'm not at home there. As far as I see, you have a FreeMarkerConfigurer bean which has a freemarkerSettings property, which is a Properties object that's eventually is passed to FreeMarker's Properties-based configuration API. So there you should be able add an object_wrapper property that refers to the class name of the ObjectWrapper to use (or it could just be beans to use the default BeansWrapper instance like maybe Struts does). Problem is, the property-based API is rather limited, and so you can't both create and configure (call setSimpleMapWrapper) a BeansWrapper there. You could do that in the spring configuration file of course, but I don't see a way to inject that into the FreeMarkerConfigurer, unless you create the whole freemarker.template.Configuration object as a bean, and inject that into the FreeMarkerConfigurer with the configuration property of it. So maybe the easiest workaround is extending BeansWrapper to override the default of simpleMapWrapper, and then referring to the class of that extending class via object_wrapper. (Just in case somebody reads this later, it's probable that FreeMarker 2.3.21 will extended the properties configuration API so that you can just set object_wrapper to BeansWrapper() { simpleMapWrapper = true }.)
With Spring, how can i retrieve the following Controller attributes in the view?
Controller name
Controller's #RequestMapping URI
Action method name
Action method's #RequestMapping URI
One approach which i have tried is by creating a subclass of HandlerInterceptorAdapter and overriding postHandle. I register my subclass as an mvc:interceptor for a list of given paths - which is clunky to maintain but was the only way to avoid my interceptor being called for ResourceHandler requests (which i don't want). In my postHandle i can easily add the 2 name attributes, but not the URIs...
Parsing from the HttpRequest object requires constraints on all Controller RequestMappings. I.e. i must always map /Controller/Action or equiv scheme. Quite limiting.
Creating an ApplicationContext and querying that with the requestURI is too long-winded.
I am thinking about dropping the HandlerInterceptorAdapter and instead defining a BaseController for all my controllers to extend.
I wanted to ask before i do this, is there a better approach?
You haven't stated why you need to do this (it sometimes helps to include your motivation, as others can suggest alternative approaches).
But I'm guessing that the Spring 3.1 features loosely termed "end point documentation" may do what you are asking... See RequestMappingHandlerMapping in the Spring documentation which doesn't provide a lot of detail, so this example project is the best place to see it in action:
Spring MVC 3.1 Demo App
example controller
example JSP page
I'm trying to convert a struts 1 application to Spring MVC 3.0. We have an form with quite a few parameters, most of which where automatically binded in struts. However there where a number of fields in the format fieldName_# where # is a number that we manually bound by looping through the request.
I'm looking for a tidier way to do this in Spring mvc, but don't know where to start.
Ideally we should have them as fieldName[#] and it would be easier, but we cannot change this and have to keep the fieldName_# format. Also the number of these fields that are sent in the request are unknown.
One way to achieve this is by wrapping the servletRequest and implementing the getParameter (and associated methods) such a way that parameters with name fieldName_# are returned as fieldName[#]. A servletFilter would be one option to wrap the request.
i have a login-validation.xml which define some basic field validation rules.
however that's not enough for me.
i need to do some more database lookup and i consider this as part of my validation logic.
how can i do both xml validation and my database lookup in one go?
i suppose i will write something like
public void validate() {
1) struts2-validation.xml validation();
2) myDatabaseLookup() and addFieldError() or addActionError();
}
my problem is, what is the api i can use for (1)?
or, how can i look at the code of this xml validation filter class? in fact i would also make the definitions in validation.xml available to javascript usage... i guess i would need to do some translation from xml to javascript logic, but first of all, how can i access the validation.xml api in java code?
Your best choice is to create a validator... Take a look here for some information -
Custom Validator
There are a few things to keep in mind... I don't know if the ObjectFactory will instantiate and inject your validator, so you might not have all the features of dependency injection. If your custom validator isn't injected, file a bug, I'll take a look at it.
After you create your validator and register it in your app, you can add it to the validation.xml file.
(side note, I know that I am pointing to the XWork docs, but Struts2 uses XWork internally for most of it's validation capabilities)