I'm using Freemarker templates to generate HTML. I have this line repeated in several templates:
<link href="/css/main.css?v=${css_version}" rel="stylesheet">
I want to be able to specify a value for css_version just once, and use it in all my templates. How can I do this?
Possibly like this:
Configuration cfg ...
...
cfg.setSharedVariable("css_version", "1.2.3");
Note that you should do this where you set up your singleton Configuration instance, and it's not thread safe to call setSharedVariable later. So if css_version has to change without recreating the Configuration, then instead of a String simply use a custom TemplateScalarModel implementation that reads the version number from some thread-safe source. (That is, the value of a shared value can change over time, as far as the template sees it, even though the actual shared variable object isn't replaced.)
Related
We have a pretty old project where we have a lot of custom attribute definitions but do not trust our sites/site_template/meta/system-objecttype-extensions.xml to be complete.
Does anybody know of a way to remove a defined set of custom attribute definitions automatically? We can identify quite a lot that are definitely not used anymore but I'm missing the DELETE import functionality available for other types of data in SFCC.
Tx a lot for your help!
What to do, so I wrote my own parser / analyser / merger: https://github.com/Andreas-Schoenefeldt/SFCCAnalyser#combine-and-analyse-system-objecttype-extension-xml-files
It can be used like this:
put all xml files you would like to merge into one in ./data/meta-xmls/
run node combine-xml.js
the resulting merged and cleaned xml file will be in ./data/meta-xmls/combined.xml
The resulting file will contain all custom attribute definitions accross the systems, so it can then safely imported checking the Delete existing attribute definitions and attribute groups not contained in the import file, including attribute definitions marked as "externally-defined".
I have updated the variable registry to point to a custom properties file and i am able to read those in my processors using expression language with out any issues.
How ever i want to read them in my Custom Processor's (extending the AbstractProcessor) onTrigger()
I tried flowFile.getAttributes() and context.getAllProperties() and it is not getting picked up.
Appreciate any inputs.
Thanks
To clarify, you want to reference the value of these externally-defined variables inside the application logic of your CustomProcessor#onTrigger() method?
You can:
Load the variable definitions by querying NiFiProperties#getVariableRegistryProperties() or NiFiProperties#getVariableRegistryPropertiesPaths. Once you have a reference to the variable definitions, you can parse and use them as you wish.
You can reference them via the flowfile attributes or processor properties if those attributes or properties support Expression Language and it is appropriately scoped. The PropertyDescriptor will list expressionLanguageSupported() and return an ExpressionLanguageScope, which is an enum consisting of NONE, VARIABLE_REGISTRY, and FLOWFILE_ATTRIBUTES (which also includes the VR).
I don't understand the scenario where you want your code to load custom variables that aren't controllable by the flow administrator, which would be populated via processor properties or flowfile attributes. If you really feel you need to access custom variables that aren't available via the context or flowfile, you can use Option 1 above, but you could also theoretically store those variables in environment variables, System properties, etc.
I am trying to process the freemarker template through template.process(,) and loading the template from database(mongo) through the TemplateLoader interface.Here I want to define the different data-model for the included template. Mainly I want to define template.process for an individual included template.
Also, is there any way through which we can execute the business logic while processing the template.
Will it be a good idea to process the template while implementing the templateloader interface?
If by including a template you mean using <#include ...>, that's basically for composing a single template from reusable fragments, so it can't have a different data-model than the including template. But you could use your own custom directive implementation (see TemplateDirectiveModel) to do a whole new template processing inside another, just pass Environment.getOut() to Template.process so that it writes to the output of the parent template processing.
Is there any strong reasons to choose one over the other when declaring the mappings for url resources?
#RequestMapping(Mappings.USER)
vs
#RequestMapping("${mappings.user}")
I understand that property files can be modified after deployment, and that might be a reason to keep it in properties if you want it to be changed easily, right? But also I think changing them easily could be undesirable. So for those with experience, which do you prefer, and why? I think a constants file might be easier to refactor, like if I wanted to change the name of a resource I would only have to refactor inside the constants class vs if I refactored properties I would have to refactor in the properties file and everywhere that uses the mapping (Im using eclipse and as far as I know it doesnt have property name refactoring like that). Or maybe a third option of neither and declaring them all as literals inside the controllers?
It all depends on your use case. If you need the change URIs without recompilation, property files is the way to go. Otherwise, constants provide type safety and ease of unit testing that SPEL doesn't. If you're not gonna change or reuse them (for example, same URI for GET and POST is very common), I don't see any need for constants at all.
I have a case where I have some common functionality within a macro. I have coded that as a macro, but don't want this to be accessible outside the current ftl (just like a private instance variable in Java). One way to do this is to keep the inner macro in a separate file and only include it in this ftl, but that seems to be a bit of a hack. Any suggestions?
There are no private macros in FreeMarker.
If your only concern is namespace pollution (as opposed to security), you may want to look into #import. If you just want to communicate that this macro shouldn't be called from outside, you may start its name with _; that means nothing to FreeMarker, but kind of documents that it's something you shouldn't call unless you know what you are doing.