I have a WAR archive compiled with maven.
I want to insert the compilation timestamp in a jsf page.
How can I change a string in a jsf page at compilation time ?
Example
<div>Compiled at (copilationTime)</div>
Must became
<div>Compiled at 2017-01-01 15:50</div>
If it is too complicate, I have an applicationscooped bean and i wrote
<div>Compiled at ${MyApp.compilationTime}</div>
But in my class how can i set 'xxxx'?
public class MyApp{
String compilationTime = 'xxxx';
public String getCompilationTime(){
return compilationTime;
}
}
I think you're talking about a variation of resource filtering via maven-resources-plugin. The idea is this:
You ask Maven to filter a certain resource (either a src/main/resources resource, or a variation of it, via maven-resources-plugin, a src/main/webapp resource via maven-war-plugin) in which you have placed the Maven pre-defined variable ${maven.build.timestamp}
You make sure that the filtered resource is included in your project
You read that resource either via Class.getResourceAsStream (or a variation of it), or via servlet mechanisms (depending where you place it).
You use the value in your JSF.
Please note that you can ask Maven to replace a filter a variable directly in your JSF and cut some steps.
From this answer you can get a reference to a file:
final File classFile = new File(MyApp.class.getProtectionDomain().getCodeSource().getLocation().getPath());
and then from here you get the property:
BasicFileAttributes attr = Files.readAttributes(classFile, BasicFileAttributes.class);
String compilationTime = attr.creationTime().toString();
You can use #CompileTime from Kolobok and create a field
#CompileTime
private static long ct; // This field will contain compilation time in ms
Related
In a panel that is supposed to be loading a JS resource, I add a Behavior with the following method to the panel:
#Override
public void renderHead(Component component, IHeaderResponse response){
response.render(JavaScriptHeaderItem.forReference(new
JavaScriptResourceReference(relativeClass,
WebApplication.get().getServletContext().getContextPath() +
jsRef)));
}
I can see from stepping through in debug that the name parameter is the context path prepended to the url of the resource, which is exactly what I want! But when the website is run, the panel looks at localhost:8080/context/scopeURL/context/resourceURL instead of localhost:8080/context/resourceURL. The scope can't be set to null, so what do I have to use for the name parameter to access the resource properly?
Classes are kept in a separate directory structure within the root directory from the scripts that I am trying to load, otherwise this wouldn't be such a problem. Answers which work for Wicket 6.x should work for this version, I think.
JavaScriptResourceReference uses the Class "relativeClass" as a scope and encodes it in the url.
You need to use ContextRelativeResourceReference(jsRef)
Is there any way of loading the Freemarker templates directly without having need to first load the Directory from which templates will be loaded or setting the Class relative to which templates will be loaded.
i.e Is there any way so that i can load a template like
Template template = getTemplate("PathToTemplate/myTemplate.ftl");
I need this, because user specifies the complete path to ftl files. So,first i have to separate directory name and file name, then i am doing
Configuration cfg = new Configuration();
int indexOfLast = templatePath.lastIndexOf("\\");
String dir = templatePath;
String fileName="";
if(indexOfLast>=0){
dir = templatePath.substring(0,indexOfLast);
fileName= templatePath.substring(indexOfLast+1,templatePath.length());
}
cfg.setDirectoryForTemplateLoading(new File(dir));
Template template = cfg.getTemplate(fileName);
I do not want to do all this.
Templates can be created by directly calling a Template constructor, to which you pass a String or Reader as argument. Then of course you get that Reader or String from wherever you want. This approach has two disadvantages though:
Other templates won't be able to #import or #include those templates, as FreeMarker doesn't know how to load them (only you do)
Caching those templates (if that's needed anyway) is up to you
If the above two is a problem for you, then see Seelenvirtuose's answer: create a TemplateLoader that interprets the template names as full paths.
As of your example code, know that the Configuration instance will clear its template cache every time you replace the TemplateLoader. Also note that it's not thread-safe to do.
The getTemplate method is heavily overloaded. As per the documentation the method getTemplate(String, Locale, String, boolean) will eventually be called regardless which getTemplate method you called.
This method's documentation expresses the following:
The exact syntax of the name is interpreted by the underlying TemplateLoader, but the cache makes some assumptions. First, the name is expected to be a hierarchical path, with path components separated by a slash character (not with backslash!). The path (the name) given here must not begin with slash; it's always interpreted relative to the "template root directory".
There are two notable things:
The name parameter is already handling a hierarchical path, but must not begin with a slash. So maybe you could set the configuration's directory once to the root of your disk and then simply provide the full path (but without the leading slash).
The documentation explains something about a TemplateLoader. So you can simply write an implementation of that interface for loading the template. In that implementation you have full hands on the provided name.
I am replacing the property factory which is used to the load the configuration files with spring. So technically now, my configuration files should be loaded using spring DI via Apache
commons configurations.
So far I have created an Action class and a POJO view class which has the getters and setters for Loadtime, FileModified time, File name etc. The Action has a list of configuration classes injected into the constructor and in the execute method I am looping over the configuration classes creating a simple view object for each one. Then I am setting the value to the my view object which I get from config something like this:
public final String execute() {
configViewList = new ArrayList<ConfigurationViewObject>();
if ((this.configurationList != null) && (this.configurationList.size() != 0)) {
for (PropertiesConfiguration config : configurationList) {
ConfigurationViewObject view = new ConfigurationViewObject();
view.setFileName(config.getFileName());
view.setFileModificationTime(new Date(config.getFile().lastModified()));
configViewList.add(view);
}
return SUCCESS;
} else {
addActionError("List is null.");
return Action.ERROR;
}
}
Well, now I want to find out the load time. Any idea how to find the time when the spring loads the file.I have entirely searched PropertiesConfiguration class and File class if there is any method which gets it for me, however couldn't find any. I would appreciate the much awaited help.
Its very tricky to find this because Spring will never expose this to outside world and thats correct, why would anyone want to know when config file gets loaded?
But still , here is what i would do. Spring config will be loaded when Spring creates loads a class which needs some properties to be set [This is not document officially anywhere but thats how it shld be logically]. Now next part is to find out which class instance needing properties is created first. Again no starighforward way for this but still an appox. way would be to put a System.currentTimeMillis() in Class's constructor. So this will give you an appox. time of when property file will be loaded.
For a straightforward way to do this... you can try calling long before = System.currentTimeMillis() before the call to retrieve properties, and another long after = System.currentTimeMillis() call right after the the properties are retrieved, and seeing the value of the difference, after - before.
What exactly is the ResourceResolver? More important, how do you use it? I'm struggling to find a simple example. So, say I have a path and want to use the resource resolver to see if the path resolves to a resource. How would I do that? I know this is wrong but if someone can correct this it would help.
Iterator<String> nodeSample = getResource("title");
return nodeSample
The RequestResolver, to quote the javadoc, defines the service API which may be used to resolve Resource objects.
You typically access it in a SlingServlet by calling request.getResourceResolver() or in a script ( JSP script for instance ) under the resourceResolver variable. For more details on variables on scripts see Scripting variables in the Sling wiki.
One you get a hold of it you can use it to access resources in the content tree:
Resource resource = requestResolver.getResource("/content/my/resource");
if ( resource != null ) // bingo!
To display a resource's properties I usually adapt it to a ValueMap and then extract the properties
ValueMap properties = resource.adaptTo(ValueMap.class);
String title = properties.get("jcr:title", String.class);
What is the best way to enable my webapplication to use JSF files stored in the database?
I'd like to be able to dynamically (during runtime) create new JSF pages which will be made available without having to redeploy the application.
So in other words: I would like to store the bigger part of my JSF pages in the database and would like JSF to use the database as a datasource for getting JSF files.
I've thought long about a solution and found some possible ways. However, I haven't been able to implement either of them.
Whenever a new page has to be added/removed: manipulate the files in the classpath (e.g. remove or add a file to the .war file)
Extending the classpath of the webapplication so it will be able to get files from an at runtime defined location (i.e. /tmp or directly using a database connection)
Provide JSF with a way to find resources another way ( this doesn't seem possible? )
My environment:
Java SE 6
Jetty as servlet container
Mojarra as jsf implementation
Now, my question:
Is it possible for someone to let JSF find pages at a location other than the default classpath, preferably the database?
Any response is greatly appreciated!
1: Whenever a new page has to be added/removed: manipulate the files in the classpath (e.g. remove or add a file to the .war file)
This is definitely possible if the WAR is expanded. I am not sure about Jetty, but it works for me with Mojarra 2.x on Tomcat 7 and Glassfish 3. Just writing the file to the expanded WAR folder the usual Java IO way suffices.
File file = new File(servletContext.getRealPath("/foo.xhtml"));
if (!file.exists()) {
OutputStream output = new FileOutputStream(file);
try {
output.write(bytes); // Can be bytes from DB.
} finally {
output.close();
}
}
This needs to be executed before the FacesServlet kicks in. A Filter is a perfect place. See also this related answer:
How to create dynamic JSF form fields
2: Extending the classpath of the webapplication so it will be able to get files from an at runtime defined location (i.e. /tmp or directly using a database connection)
You can package Facelets files in a JAR file and put it in the classpath and provide a Facelets ResourceResolver which serves the files from the JAR on when no match is found in WAR. You can find complete code examples in the following answers:
how to share a jsf error page between multiple wars
How to create a modular JSF 2.0 application?
3: Provide JSF with a way to find resources another way ( this doesn't seem possible? )
You've plenty of play room in the custom ResourceResolver.
Nice question. BalusC's answer is - as always - complete and right.
However, if your point is to create an application where gui is built dynamically, there is a way that might serve you better (depending on what you really want to achieve).
JSF views are similar to Swing forms - they are just a bunch of JavaBeans(tm) glued together. The big difference is that when a field is bound to an EL expression, you do not use standard accessors, but rather a special method (setValueExpression).
This means you can build your GUI from objects (the concrete classes can be found in javax.faces.component.html) in a pure programmatic way and then use binding attribute to show it on page. Something like:
<h:form>
<h:panelGrid binding="#{formBuilder.component}"/>
</h:form>
And then in the managed formBuilder bean:
#PostConstruct
public void init() {
HtmlInputText hit = new HtmlInputText();
// properties are easy:
hol.setStyle("border: 2px solid red");
// binding is a bit harder:
hit.setValueExpression("value", expression("#{test.counter}", String.class));
HtmlOutcomeTargetLink hol = new HtmlOutcomeTargetLink();
hol.setValue("link leading to another view");
hol.setOutcome("whatever");
component = new UIPanel();
component.getChildren().add(hit);
component.getChildren().add(hol);
}
private ValueExpression expression(String s, Class c){
return FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
FacesContext.getCurrentInstance().getELContext(),
s, c
);
}
The example above builds a static panel, but it would be possible to:
create an object model of your GUI
map the model to database (with hibernate or another orm)
write some kind of adapter or bridge to build JSF objects from your object model
make a managed bean that receives the form id, grabs the relevant form from database, builds a JSF panel out of it and presents it as a property, ready to be bound.
This way you could have just one static xhtml with a single tag and use it to present any number of dynamic forms.
As I said, this method could be better than just storing files, but not necessarily. If you just want to save yourself the hassle of redeployment, this is a huge overkill (then again, you do NOT need to redeploy JSF applications just to change forms). If on the other hand your goal is to have something like user-defined and edited forms, having a good object model and storing it in a proper way could be a good idea.
The bumps ahead would be:
navigation (perhaps a custom navigation handler would suffice?)
problems with generating plain html
possibly some problems with lifecycle of view scoped forms