Java EL: Access nested properties - java

Given a class A:
public class A {
private String foo;
//getter, setters etc...
}
can one reference the foo property if an A object itself is exposed as property in a managed bean, e.g:
#ManagedBean
public class SomeBean {
private A a;
//getter, setters etc...
}
#{someBean.a.foo}

Indeed, it will work. Both for setting and obtaining the value. An input such as:
<h:inputText value="#{someBean.a.foo}" />
will both obtain the value to display it and set the new defined value by doing either
beanInstance.getA().getFoo();
or
beanInstance.getA().setFoo("newValue");
Just take into account that for this to work and avoid getting a NullPointerException, getA() cannot return null, meaning that your a object must be instantiated.

Related

Can you serialize object's property instead of a whole object in Spring REST? (object being a field of a class)

To clarify - I have some class in a Spring REST project which has an instance of some other class as one of its fields.
public class Event {
...
...
...
private Location location;
}
The location object has some id of type int. So when serializing Event object is it possible to somehow only attach the location.id field instead of the whole serialized location object?
If you are allowed to modify Location class, you can try #JsonValue annotation on the Location.id field:
public class Event {
private String someField;
private Location location;
}
public class Location {
#JsonValue
private int id;
}
It will get serilized to:
{
"someFiled": "someValue",
"location": 122
}
If you prefer different name of the serialized field, use #JsonProperty:
public class Event {
private String someField;
#JsonProperty("locationId")
private Location location;
}
public class Location {
#JsonValue
private int id;
}
{
"someFiled": "someValue",
"locationId": 122
}
Another option I can think of would be using #JsonUnwrapped in conjunction with #JsonIgnoreProperties. The Location class doesn't need to be changed in this case, but all properties to be excluded need to be explicitly listed.
public static class Event {
private String someField;
#JsonUnwrapped(prefix = "location_")
#JsonIgnoreProperties({"fieldA", "fieldB", ...})
private Location location;
}
{
"someFiled": "someValue",
"location_id": 122
}
Bare in mind that both solutions will break deserialization.
If you serialize the whole Event object I believe it is not possible to avoid serializing the location object too as it is one of its properties. You could, however, attempt to serialize the properties of the object and not the object itself, in which case you could serialize location.id and not the whole location object.
The only problem is that you would have to find some way to organize this data in the file that you serialize it to, or just create a different file for each property.

AWS DynamoDBMapper save method keeps throwing `DynamoDBMappingException: not supported; requires #DynamoDBTyped or #DynamoDBTypeConverted`

I followed everything that is outlined here - https://github.com/derjust/spring-data-dynamodb/wiki/Use-Hash-Range-keys. But still no luck.
I have a DynamoDB table with a hash key and a sort key.
Here is my entity class RecentlyPlayed.class
#DynamoDBTable(tableName="some-table")
public class RecentlyPlayed {
#Id
private RecentlyPlayedId recentlyPlayedId;
// ----- Constructor methods -----
#DynamoDBHashKey(attributeName="keyA")
// Getter and setter
#DynamoDBRangeKey(attributeName="keyB")
// Getter and setter
}
Here is my key class RecentlyPlayedId.class
public class RecentlyPlayedId implements Serializable {
private static final long serialVersionUID = 1L;
private String keyA;
private String keyB;
public RecentlyPlayedId(String keyA, String keyB) {
this.keyA = keyA;
this.keyB = keyB;
}
#DynamoDBHashKey
// Getter and setter
#DynamoDBRangeKey
// Getter and setter
}
Here is my repository interface RecentlyPlayedRepository
#EnableScan
public interface RecentlyPlayedRepository extends CrudRepository<RecentlyPlayed, RecentlyPlayedId> {
List<RecentlyPlayed> findAllByKeyA(#Param("keyA") String keyA);
// Finding the entry for keyA with highest keyB
RecentlyPlayed findTop1ByKeyAOrderByKeyBDesc(#Param("keyA") String keyA);
}
I am trying to save an object like this
RecentlyPlayed rp = new RecentlyPlayed(...);
dynamoDBMapper.save(rp); // Throws that error
recentlyPlayedRepository.save(rp); // Also throws the same error
I am using Spring v2.0.1.RELEASE. The wiki in the original docs warns about this error and describes what to do to mitigate. I did exactly what they said. But still no luck.
The link to that wiki is here - https://github.com/derjust/spring-data-dynamodb/wiki/Use-Hash-Range-keys
DynamoDB only supports primitive data types, it does not know how to convert your complex field (recentlyPlayedId) into a primitive, such as a String.
To show that this is the case, you can add the annotation #DynamoDBIgnore to your recentlyPlayedId attribute like this:
#DynamoDBIgnore
private RecentlyPlayedId recentlyPlayedId;
You also need to remove the #id annotation.
Your save function will then work, but the recentlyPlayedId will not be stored in the item. If you do want to save this field, you need to use the #DynamoDBTypeConverted annotation and write a converter class. The converter class defines how to convert the complex field into a String, and then uncovert the String into the complex field.
Removing getters/setters for the #Id field fixed the problem for me. This is suggested in https://github.com/derjust/spring-data-dynamodb/wiki/Use-Hash-Range-keys
not supported; requires #DynamoDBTyped or #DynamoDBTypeConverted",
i was getting this error when i defined model class with field JsonNode,i converted it to MAP<String,String>,now it is working fine

Java annotation: elements declared as method but value set as attribute

When we create a custom annotation, we declare elements as methods and later set values as if they were attributes.
For example, here we have declared a custom annotation ComponentType with elements name() and description() that look like methods.
public #interface ComponentType {
String name();// declared as method
String description();
}
When the annotation is used, they look like the below:
#ComponentType(name = "userContainer", // value looks like an attribute
description = "a user container")
public class UserEntity { }
My question is: Why doesn't Java allow to declaring elements as attributes, like this?
public #interface ComponentType {
String name; // Compilation Error
String description;
}
If the properties of an annotation weren't defined as abstract methods in an interface, they would have been members. Something like:
public #interface ComponentType {
String name;
String description;
}
However, all the members in an interface are implicitly final (and static) and the above code does not compile, because name and description aren't initialized.
But if they were actually initialized with some values:
public #interface ComponentType {
String name = "name";
String description = "description";
}
then snippets like the following one wouldn't have been possible:
#ComponentType(
name = "userContainer" //cannot assign a value to a final variable
, description = "a user container")
My observation is:
Java consider annotations as special type of interface so:
Like interface we can declare only final attributes in an annotation:
String appName = "test application";//final attribute, never reset value
Annotation may contains only abstract methods(a method that is declared without an implementation).
public #interface ComponentType {
String name();// declared as abstract method
When we annotated elements(e.g. class, method, attribute) by annotation we need to set return value of those abstract methods, which looks like attribute but actually acts as an implementation.
#ComponentType(name = "userContainer"//set return value of method name()
We can use the values we set during annotated elements(e.g. class, method, attribute) by simply calling abstract methods of annotation.
Annotation annotation = annotatedClassObject.getAnnotation(ComponentType.class);
ComponentType componentType = (ComponentType) annotation;
String someName = componentType.name(); //returns value set during annotating
So like as interface,
Annotation never support to declare any non-final attributes.
Annotation may contains some abstract methods and we need to set return value of
abstract method during annotated elements(e.g. class, method,
attribute).
Expecting More Feedback / Answer

JSF: Binding two values from the same form field

I am setting a value in the login-bean when the user logs-in
using
--Login-bean
setMailNickname(mailnickname);
And in the info page I am able to retrieve the same value using
--InfoPage
<h:inputText value="#{login.mailNickname}" />
Now on the info page I am taking some more info from the user and saving all of them in the database, As one of the value is from the login form bean it is prepopulating on the Info-page but how to assign the same value to the info-page bean variable-
InfoBean.mailNickname
so that it can be saved into the database with the other fields which the user provides.
How can I assign the value to the infopage bean variable?
You can inject LoginBean into InfoBean, so that you can have a reference to its fields. As I understand one of your beans is at least #SessionScoped. You didn't provide that information, so I'd go as far as to guess that LoginBean is used for logging into your application or something like that and InfoBean to hold that information for future reference. Following that chain of thinking your InfoBean would look like that:
#ManagedBean
#SessionScoped
public class InfoBean {
private String mailNickname;
public String getMailNickname() {
return mailNickname;
}
public void setMailNickname(final String mailNickname) {
this.mailNickname = mailNickname;
}
// other fields, methods...
}
and your LoginBean then would hold reference to session-scoped InfoBean:
#ManagedBean
#ViewScoped
public class LoginBean {
private String mailNickname;
public String getMailNickname() {
return mailNickname;
}
public void setMailNickname(final String mailNickname) {
this.mailNickname = mailNickname;
}
#ManagedProperty("#{infoBean}")
private InfoBean infoBean;
public void setInfoBean(final InfoBean infoBean) {
this.infoBean = infoBean;
}
/** Method you use for populating */
public void populateInput(final String mailNicknameFromDb) {
setMailNickname(mailNicknameFromDb);
infoBean.setMailNickname(mailNicknameFromDb);
}
}
Remember about getters and setters for those fields as well as setter for managedProperty and be careful about scopes (you can't for example inject request-scoped bean into application-scoped bean, because the request-scoped one would probably not exist yet when creating application-scoped one).

No getter method available for property for bean with name

I'm trying to populate a select with Struts. However, I'm getting this error message:
No getter method available for property label under name com.packagename.branchImpl
There is no variable called 'label' in the class in which its looking either, so I don't know how it is looking for label
form class is a very typical entity class
any suggestions as to why this error occurs?
It could be a typo with <cain:optionsCollection should be <html:optionsCollection. The last tag uses a property attribute for the collection of beans that have label and value properties. If you have a different property names in the collection bean then it could be specified using the label and value attributes of the tag. For example if you have a collection List<MyBean> and
public class MyBean implements Serializable {
private String key;
private String name;
//getters and setters for both
}
then you should use
<html:select name="querySwiftLogForm" property="branch" >
<html:optionsCollection name="querySwiftLogForm" property="branchList" label="name" value="key"/>
</html:select>
If you don't have a bean that you could use with the collection, then you could use LabelValueBean. And you need to fill the collection with the instances of that bean. Then lable and value attributes not necessary for that bean because it will use the defaults.
Also, if you use the form that is mapped to the action then name attribute is not necessary.
No getter method available for property for bean with name
I'm not posting complete error and jsp and all so just understand
First Check properties file if you are using it.
Then check properties name -- like name, password
And check the setter and getter method where you define. Check very carefully.
Then you find that setter and getter are different then it should be
For example:
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
While it would be as:
public void setname(String name)
{
this.name = name;
}
public String getname()
{
return name;
}
Just a little mistake while using setter and getter.
It's looking for a label property because that's what optionsCollection does:
This tag operates on a collection of beans, where each bean has a label property and a value property. The actual names of these properties can be configured using the label and value attributes of this tag.

Categories

Resources