HTL Access Property Without Getter - aem

I'm writing an AEM component and I have an object being returned that is a type from an SDK. This type has public properties and no getters. For simplicity, it might be defined like this:
class MyItem {
public String prop1;
public String prop2;
}
Now normally, I would need a getter, like so:
class MyItem {
public String prop1;
public String prop2;
public String getProp1() {
return prop1;
}
}
But I do not have this luxury. Right now, I've got a Java implementation that uses another type to resolve this, but I think it's sort of crazy that HTL doesn't allow me to just access prop1 directly (it calls the getter). I've reviewed the documentation and can't see any indication of how this could be done. I'd like to be able to write:
${item.prop1}
And have it access the public property instead of calling getProp1().
Is this possible?

You don't need getters for public fields if those fields were declared by your Java Use-class. There's actually a test in Apache Sling that covers this scenario:
https://github.com/apache/sling/blob/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/use/repopojo.html
This also applies to Use-classes exported from bundles.
For Sling Models using the adapter pattern [0] I've created https://issues.apache.org/jira/browse/SLING-7075.
[0] - https://sling.apache.org/documentation/bundles/models.html#specifying-an-alternate-adapter-class-since-110

From the official documentation
Once the use-class has initialized, the HTL file is run. During this stage HTL will typically pull in the state of various member variables of the use-class and render them for presentation.
To provide access to these values from within the HTL file you must define custom getter methods in the use-class according to the following naming convention:
A method of the form getXyz will expose within the HTL file an object property called xyz.
For example, in the following example, the methods getTitle and getDescription result in the object properties title and description becoming accessible within the context of the HTL file:
The HTL parser does enumerate all the public properties just like any java enumeration of public fuields which include getters and public memebers.
Although it is questionable on whether you should have public variable but thats not part of this discussion. In essence ot should work as pointed by others.

Related

Why should I avoid wrapping fields in getters and setters?

I am building a Flutter app. I have a class that looks like this:
class ToDo {
String _title;
bool _done;
String get title => _title;
void set title(String newTitle) { _title = newTitle; }
bool get _done => _done
void set done(bool done) { _done = done; }
}
But the Dart linter is complaining that I should "Avoid wrapping fields in getters and setters just to be safe". However, this doesn't make much sense to me. Right now the getters are useless, but what if in the future I need to do some kind of processing before accessing a variable from outside? All I'll have to do is update the getters. However, if the properties were public and being accessed directly, I would have to update the whole codebase if some business rule changed.
So what is the point of this warning? Or, in other words, why creating "useless getters" would be a bad practice?
However, if the properties were public and being accessed directly, I would have to update the whole codebase if some business rule changed.
Ask yourself this: what exactly would you need to change in your Dart codebase if you had to change a public member to use an explicit getter and setter instead?
In most languages, getters and setters look like method calls to consumers. If you wanted to replace a public data member with a public getter and setter, that would be a breaking API change, requiring changes to everything that uses it.
Dart is not like that. Getters and setters do not look like method calls to consumers; they are indistinguishable from direct member access. (Having a public data member implicitly declares a corresponding getter and setter as part of the class's interface.) Changing a public data member to a public getter and setter would not require any changes to callers, so providing trivial getters and setters around private member variables provides no benefit.
(This is also explained by the documentation for the unnecessary_getters_setters lint that you encountered.)
Incidentally, the unnecessary_getters_setters lint should occur only if you provide both a getter and a setter (which is not what your example code does). If you provide only one, then it would no longer be equivalent to a public data member.
Just to add to this I would like to make an additional comment. This error goes away if you do something else within the setter, not just set the value. In my use case I was setting a value in a Provider and was calling notifyListeners().
By adding this additional functionality the lint warning disappears. I guess because the setter is doing more than just setting the value.

BsonSerializationException when passing concrete Parameter in constructor to fill more general Property with .net driver

I have a Identity class that is extended by two classes StringIdentity and GuidIdentity. I want to use them in Objects as Property and save them in a MongoDb. For Example a class would look like this:
public class MyEvent : IDomainEvent
{
public MyEvent(GuidIdentity entityId)
{
EntityId = entityId;
}
public Identity EntityId { get; }
}
IDomainEvent forces me to implement the Identity Property, so I can (and do not want to) change the property type to GuidIdentity.
When I deserialize my class I get an exception like this:
Creator map for class Microwave.Eventstores.UnitTests. MyEvent has 1
arguments, but none are configured.
Which seems logical according to the .net driver doku, as my property does not match the type of the parameter and therefore can not be serialized. I had the solution to use the Identity as constructor parameter or make the constructor private and instantiate the class with a static Create method that takes the GuidIdentity as parameter. I also messed around with the BsonClassMap, but I really do not want to write all this kind of duplicate code for every class that implements IDomainEvent
So is there a way to tell the .net Driver to use the concrete class from the constructor instead of the more general PropertyType for all Types? Some kind of silver bullet solution? ;)
I am very new to mongodb so I am not aware of all the tricks that come with it, maybe someone can help me out here.

BeanWrapperFieldSetMapper alternative, to avoid setTargetType/setPrototypeBeanName

I need a way to get rid of fieldSetMapper.setTargetType because I do not want to add a POJO every time I have a new file to read. Is it possible?
Springbatch has a few FieldSetMapper implementations available out-of-the-box : Documentation (FieldSetMapper)
You can for example use a PassThroughFieldSetMapper to get a FieldSet object in your processor. You can do the same with an ArrayFieldSetMapper to get an array object.
But in your case, I think you need to implement your own FieldSetMapper. It could for example have a names property (with a setter) and a targetClass property (with a setter). Using Reflect, you could then cast the object to your desired class and call setters according to the names passed as arguments.
Here's what a FieldSetMapper looks like :
#Override
public Report mapFieldSet(FieldSet fieldSet) throws BindException {
T object;
object.setField(fieldSet.readString(0));
return object;
}
Here's what Reflect looks like :
Method method = object.getClass().getMethod(methodName);
method.invoke(object);

JAX-RS consuming a custom object list inside a custom object

What is the way to consume a list of custom objects inside another custom object in JAX-RS CXF implementation? As an example my object looks like below
#POST
#Produces({MediaType.APPLICATION_JSON})
#Path("test")
public Response myMethod(MyCustomObject myCustomObject) {
Inside MyCustomObject it has a list of another custom object which reside inside this as an inner class
public class MyCustomObject {
private List<MyInner> innerObjects;
public class MyInner {
private String property;
....
}
....
}
Request JSON object is passed as the POST body of the request. When I debug this I could get the MyCustomObject passed properly while I am sending the innerObjects list as null. But it seems its not picking this correctly when I have this array based structure there with a custom object. Additionally instead of this custom object array when I have a primitive type or a string based array the service works fine. How to deal with the above scenario.
It is probably because of the inner class.
Similar question here
Not sure what mapper you use (cxf default is jettison but it is all configurable), but the case is probably similar.
Great explanation here
non-static inner classes (including anonymous ones) have set of hidden variables added by compiler, passed via (hidden) constructor. And as a consequence, do not have zero-argument ("default") constructor

EXT GWT BaseModel needs to have DTO reference?

I am very new to GWT.
I am using ext-gwt widgets.
I found many places in my office code containing like,
class A extends BaseModel{
private UserAccountDetailsDto userAccountDetailsDto = null;
//SETTER & GETTER IN BASEMODEL WAY
}
Also, the DTO reference is unused.
public class UserAccountDetailsDto implements Serializable{
private Long userId=null;
private String userName=null;
private String userAccount=null;
private String userPermissions=null;
//NORMAL SETTER & GETTER
}
Now, I am able to get the result from GWT Server side Code and things Work fine, but when I comment the DTO reference inside the class A, I am not getting any Result.
Please explain me the need of that.
Thanks
Well the problem is in implementation of GXT BaseModel and GWT-RPC serialization.
BaseModel is based around special GXT map, RpcMap. This map has defined special serialization rules, which let's avoid RPC type explosion, but as side effect, only some simple types stored in map will be serialized. E.g. you can put any type inside the map, but if you serialize/deserialize it, only values of type Integer, String ,Double,Byte, Float and Short (and arrays of this types) will be present. So the meaning behind putting reference to the DTO inside BaseModel, is to tell GWT-RPC that this type is also have to be serialized.
Detailed explanation
Basically GWT-RPC works like this:
When you define an interface for service, GWT-RPC analyzes all the classes used in parameters/ return type, to create serializers/deserializers. If you return something like Map<Object,Object> from your service, GWT-RPC will have to create a serializer for each class which implements Map and Serializable interfaces, but also it will generate serializers for each class which implements Serializable. In the end it is quite a bad situation, because the size of your compiled js file will be much biggger. This situation is called GWT-RPC type explosion.
So, in the BaseModel, all values are stored in RpcMap. And RpcMap has custom written serializer (RpcMap_CustomFieldSerializer you can see it's code if you interested how to create such things), so it doesn't cause the problem described above. But since it has custom serializer GWT dosn't know which custom class have been put inside RpcMap, and it doesn't generate serializers for them. So when you put some field into your BaseModel class, gwt knows that it might need to be able to serialize this class, so it will generate all the required stuff for this class.
Porting GXT2 Application code using BaseModel to GXT3 Model is uphill task. It would be more or less completely rewrite on model side with ModelProviders from GXT3 providing some flexibility. Any code that relies on Model's events, store, record etc are in for a rewrite.