Inject JCR Properties with colon in Sling Model - java

I'm working with sling models for a project in AEM. I have my sling model setup to inject values to variables. I can setup getters to retrieve properties from the adapted resource as long as the properties have names that don't break java syntax. (For example: title)
My problem is that there are properties I need that break java syntax (for instance jcr:title,etc). I know for the get servlet for image servlet uses underscores in place of periods (file named img.GET.java, class named img_GET) and was curious if there was some character(s) I can use that will be valid java syntax that the injection strategy recognizes to replace with colons.
I know that I can retrieve these properties in other ways but I was wondering if there is a way to retrieve them using injection to keep my code dry.

Check out the following blog post:
http://labs.sixdimensions.com/blog/2014-11-21/sling-models-for-fun-and-profit/
In this, Dan provides an example of injecting (ironically enough) the jcr:title property of a Resource. You can simply use the #Named annotation and give it the name of the property you wish to inject.

Related

Property #value Spring

In spring, we can use #value annotation to refer a property value that is defined in the property file. In this approach, the way it would be something like
To have a separate property file and define the property name and value
To list this property class path in a spring config file
Finally referring the value in a class with #value annotations as
#value("{key_name}") String abc;
Other hand , we can try simply define that property value as a constant in the class something like the below and use it in the class.
public static final String key_name = "1q2w3e";
Since we have this simple approach, why we are using #value annotation approach as defined above.
Please help me to understand in detailed about it.
Using configuration values from external sources (e.g. property files) has many advantages. Some of them:
You can change the configuration without recompiling your code.
You can have multiple instances of the same binary-code running with different configuration values.
Configuration values can not only come from property-files that are bundled with your application, but from different sources like system-properties, environment-values, a database or any other custom source.
As a general rule only use constant values for things that will never change like the value of PI.
There's a big disadvantage in using the second method. Think of a scenario where you changed the language. If you were relying on the first approach you'd have to go through each class and change the value assigned to key_name. Now, if you were using the second method you'd only have to change the value assigned to key_name in one place, and that's in the properties file which is much simpler and make things more manageable.

Dynamically setting and getting bean properties in XPages

Just another Java problem (I'm a noob, I know): is it possible to use dynamic property binding in a Custom Control with a dynamic property getter in a Java bean?
I'll explain. I use this feature extensively in my Custom Controls:
<xp:inputTextarea id="DF_TiersM">
<xp:this.value><![CDATA[#{compositeData.dataSource[compositeData.fieldName]}]]></xp:this.value>
This is used in a control where both datasource and the name of the field are passed as parameters. This works, so far so good.
Now, in some cases, the datasource is a managed bean. When the above lines are interpreted, apparently code is generated to get or set the value of ... something. But what exactly?
I get this error: Error getting property 'SomeField' from bean of type com.sjef.AnyRecord which I guess is correct for there is no public getSomeField() in my bean. All properties are defined dynamically in the bean.
So how can I make XPages read the properties? Is there a universal getter (and setter) that allows me to use the name of a property as a parameter instead of the inclusion in a fixed method name? If XPages doesn't find getSomeField(), will it try something else instead, e.g. just get(String name) or so?
As always: I really appreciate your help and answers!
The way the binding works depends on whether or not your Java object implements a supported interface. If it doesn't (if it's just some random Java object), then any properties are treated as "bean-style" names, so that, if you want to call ".getSomeField()", then the binding would be like "#{obj.someField}" (or "#{obj['someField']}", or so forth).
If you want it to fall back to a common method, that's a job for either the DataObject or Map interfaces - Map is larger to implement, but is more standard (and you could inherit from AbstractMap if applicable), while DataObject is basically an XPages-ism but one I'm a big fan of (for reference, document data sources are DataObjects). Be warned, though: if you implement one of those, EL will only bind to the get or getValue method and will ignore normal setters and getters. If you want to use those when present, you'll have to write reflection code to do that (I recommend using Apache BeanUtils).
I have a post describing this in more detail on my blog: https://frostillic.us/f.nsf/posts/expanding-your-use-of-el-%28part-1%29

Java - Using Annotations/Tags to find which object to make

So let's say you have a class called Human, and a bunch of other classes that all extend Human (John, Sally, Mark). Human has an annotation "#Tags({"human"})", John has annotation "#Tags({"john"})", etc.. All classes have their corresponding tags.
My question is: how can I use these tags to figure out which object to make?
So like, a user will input either "john" "sally" or "mark" and I want to make that corresponding object...
Look at the Strategy Pattern:
a software design pattern, whereby an algorithm's behaviour can be selected at runtime
You could use this pattern to match input to a factory or as part of an enum that maps the name to a given class type (though there are several "hard-coding" issues with this approach).
As for construction of object instances, I recommend you also look at the Factory Pattern and combine the two to create these objects in an abstract manner.
I also recommend you don't tag your objects lik this, as you're hard-coding user input expectations against your codebase. At least externalise such expectations to a configuration file (.properties or .xml) so the mappings of input can change independently of the code.
I had faced similar requirements in a Project.
This is what I did,
Design a strategy to read the Class(s) : This is required because the classes are not referenced in any of your code directly. Hence these classes wont be processed by any ClassLoader automatically. Load class dynamically using Class.forName()
Generate a Factory : Make the scope of your annotation as Runtime. This will allow you to process the class files that you have read and extract your custom annotation value out of it. Then you can register the name of this class against the annotation in the factory class.
Use the factory to generate the Objects : Now you have a factory which can return the objects of your class when you pass a tag name. Use reflection to create a Object.
To know more about factory pattern please refer the link : Factory Pattern

Java .properties files as strongly typed classes

Is there way to get properties files as strongly typed classes?
I guess there are code generators but doing it with annotations would be much cooler.
What I mean is;
foo.properties file
keyFoo = valuefoo
keyBar = valuebar
maybe with
#properties(file="foo.properties")
class foo { }
becomes
class foo {
String getKeyFoo() { }
String getKeyBar() { }
}
if not shall I start an open source project for that?
ADDITION TO QUESTION;
Think we have a foo.properties file with let say more than 10 entries;
and think it is used as a simple configuration file. What I believe is that this configuration entries should be provided as a configuration class with related getXXX methods to other parts of the design. Then rest of the system accesses the configuration via provided class instead of dealing with key names and don't need to bother where configuration comes. Then you can replace this class with a mock when you are testing callers and dependency to file system goes away. On the other hand it is really nice to
get all entries in a strongly typed fashion.
So this issue is a code generation issue behind the scenes, it is nothing related to runtime. But code generation with an external something instead of annotations didn't seemed nice to me. Although I am not very much familiar with annotations, I guess this could be achieved (but I'll keep in mind that annotations can not generate classes as McDowell points)
There are countless of framework that achieve that for XML with various degree of configuration needed. The standard one bundled with Java is JaxB but it is not exactly a one liner xml persistence framework ...
The problem is that using properties file will only works better than XML (or JSON, ...) on the most trivial classes. When the class become a bit more complex, the properties file will become a nightmare. Another problem is that with trivial classes - there is not much difference between Xml and properties.
That means that the scope of the project will be rather limited. Mostly useful for project having loads of simple properties files.
In big application I worked with, strongly-type reading of properties file is done quite often using a simple factory-method.
Foo foo = Foo.loadFrom("foo.properties");
class Foo {
static Foo loadFrom(String fileName) {
Properties props = new Properties();
props.load(...);
Foo foo = new Foo();
foo.setKeyFoo(props.get("KeyFoo"));
...
return foo;
}
...
}
There is a somewhat similar project for doing configuration as statically typed files. It requires to declare an interface, but it fills in the implementation itself:
public interface AppConfig extends Config {
long getTimeout ();
URL getURL ();
Class getHandlerClass ();
}
The Annotation Processing Tool (apt) cannot modify classes (though it can create new ones). In order to modify the class at compile time, you'd probably need to edit the AST (as Project Lombok does). The simplest approach would probably be to generate the classes and then use the generated library as a dependency for other code.
Yet another way is to use a data binding framework that does this. Even one that does not seem to directly support that could work: for example, Jackson JSON processor would allow this to be done by something like:
ObjectMapper m = new ObjectMapper();
MyBean bean = m.convertValue(properties, MyBean.class);
// (note: requires latest code from trunk; otherwise need to write first, read back)
which works as long as entries in Properties map match logical bean properties, and String values can be converted to matching underlying values.
Something like JFig (ugly IMO), Commons Configuration or EasyConf?
If you want to do it statically, its a code generation problem that may be solved quite easily (for each item in file, produce a new getXXX method).
But if you want this at runtime, then you have the problem of having your code referencing method that did not exists at compile time; I don't think it can be done.
(Note that if you are looking for a project idead, the reverse, having an interface with accessor method and annotation, and an implementation generated at runtime, that relies on the annotated methods, can be done.)
The OP would like to map a property file to a Java API such that each named property in the file corresponds to a similarly named getter method in the API. I presume that an application would then use this API to get property values without having to use property name strings.
The conceptual problem is that a property file is fundamentally not a statically typed entity. Each time someone edits a property file they could add new properties, and hence change the "type" of the property file ... and by implication, the signature of the corresponding API. If we checked that there were no unexpected properties when the Java app loaded the properties file, then we've got an explicit dynamic type-check. If we don't check for unexpected (e.g. misnamed) properties, we've got a source of errors. Things get even messier if you want the types of property values to be something other than a String.
The only way you could do this properly would be to invent the concept of a schema for a property file that specified the property names and the types of the property values. Then implement a property file editor that ensures that the user cannot add properties that conflict with the schema.
And at this point we should recognize that a better solution would be to use XML as the property file representation, an XML schema driven editor for editing property files, and JAXP or something like it to map the property file to Java APIs.
I think this will solve your problem
I have written on this property framework for the last year.
It will provide of multiple ways to load properties, and have them strongly typed as well.
Have a look at http://sourceforge.net/projects/jhpropertiestyp/
It is open sourced and fully documented
Here is my short description from SourceForge:
JHPropertiesTyped will give the developer strongly typed properties. Easy to integrate in existing projects. Handled by a large series for property types. Gives the ability to one-line initialize properties via property IO implementations. Gives the developer the ability to create own property types and property io's. Web demo is also available, screenshots shown above. Also have a standard implementation for a web front end to manage properties, if you choose to use it.
Complete documentation, tutorial, javadoc, faq etc is a available on the project webpage.

make java custom annotation to mark bean properties for html cleansing

Can I use a Java custom annotation to add some code to a set or get method on a bean property to cleanse the property from bad html being input by my users? I've been looking for examples but I've not seen something that I feel I can extend.
You could define a custom annotation to add a validator to your setter, but is there a reason why you don't want to just embed validation into your bean without an annotation? The annotation mechanism might be difficult for others to understand if they ever need to work with your code.
I would do it this way: Rather than have your property be a String, define your own HtmlString (assuming an equivalent class doesn't already exist in a standard library) which can only be instantiated with valid HTML. Then, have your bean property be of that type. This would solve the validation problem in your component.
Define validation methods in the HtmlString to fit your requirements, so that every HtmlString instance is valid HTML; then, simply define a toString method. This method would likely be much easier for others to follow.

Categories