We have an existing DynamoDB table having a non key attribute "latest". We wish to remove this attribute for the newer items from now with another named "latestV2". Will just replacing the attribute from Model class with the newer one work or do we need to keep both of them and not setting the old one anymore.
Current Model Class :
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#DynamoDBTable(tableName = "Table1")
public class Table1DAO {
#DynamoDBHashKey(attributeName = "id")
private String id;
#DynamoDBAttribute(attributeName = "latest")
private Boolean latest;
}
Will this work :
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#DynamoDBTable(tableName = "Table1")
public class Table1DAO {
#DynamoDBHashKey(attributeName = "id")
private String id;
#DynamoDBAttribute(attributeName = "latestV2")
private Boolean latest;
}
The underlying setters/getters setlatest()/getlatest() should work for the new attributeName as well. Question is that while loading any old item with the old "latest" flag as true, will it break the code since that attribute is no longer modeled ?
Or should we have both the attributes in the Model class and just change the name of variable for the old attribute so that it is never set/get again like this :
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#DynamoDBTable(tableName = "Table1")
public class Table1DAO {
#DynamoDBHashKey(attributeName = "id")
private String id;
#DynamoDBAttribute(attributeName = "latest")
private Boolean latestold;
#DynamoDBAttribute(attributeName = "latestV2")
private Boolean latest;
}
Here is a good example of the table mapper. The #DynamoDBAttribute maps the field name from DynamoDB to the java class and therefore will ignore the "latest" attribute and will use "latestV2". So to answer your question you do not need to keep both attributes and modifying the old attribute does not impact your code as long as it is not mapped to any java class attribute.
Related
I have the below data object and CrudRepository implementation. When I use the CrudRepository operations both the key and value get stored as HASH data types when I would like to have them stored as String datatypes. How can I configure this behavior? I tried adding the RedisTemplate bean as below and when debugging I do see that redis template is being used, but for data conversions it uses some other KeyValueAdapter classes instead it seems, and I'm having a hard time configuring that.
#Data
#RedisHash("DATA")
#Accessors(chain = true)
public class Data implements Serializable {
#Id
private String id;
private List<AnotherObject> objects;
private Long last_updated;
}
#Repository
public interface DataCache extends CrudRepository<Data, String> {
}
#Bean
public RedisTemplate<?, ?> redisTemplate(
#Autowired RedisConnectionFactory redisConnectionFactory,
#Autowired ObjectMapper mapper) {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer(Object.class);
valueSerializer.setObjectMapper(mapper);
template.setValueSerializer(valueSerializer);
template.setHashKeySerializer(valueSerializer);
template.setDefaultSerializer(new StringRedisSerializer());
template.setEnableDefaultSerializer(false);
template.afterPropertiesSet();
return template;
}
I want to build an object where one of my class field depends on the other. Somewhat like
import lombok.Builder;
import lombok.Data;
#Data
#Builder
public class MyModel {
#DynamoDBHashkey
private String key = encrypt(value1, value2);
#DynamoDBAttribute
private String value1;
#DynamoDBAttribute
private String value2;
}
MyModel model = MyModel.builder()
.value1(1002020)
.value2(1384818)
.build();
Now when I do model.key() I want to be able to retrieve this value.
Probably I'm missing something but you could just add getter. According to documentation Annotation Type DynamoDBHashKey
Annotation for marking a property as the hash key for a modeled class. Applied to the getter method or the class field for a hash key property.
#Data
#Builder
public class MyModel {
#DynamoDBAttribute
private String value1;
#DynamoDBAttribute
private String value2;
#DynamoDBHashkey
public String getKey() {
return encrypt(value1, value2);
}
}
I am working on spring boot application ,I have one property file ,I am reading property file like below
#Configuration
#ConfigurationProperties(locations = "classpath:mail.properties", prefix = "mail")
public class MailConfiguration {
public static class Smtp {
private boolean auth;
private boolean starttlsEnable;
// ... getters and setters
}
#NotBlank
private String host;
private int port;
private String from;
private String username;
..............
}
Mail .properites
mail.host=localhost
mail.port=25
mail.smtp.auth=false
mail.smtp.starttls-enable=false
mail.from=me#localhost
This working fine ,But Instead of reading one by one property , I want to get all property keys from properties file ,How can I get this .
Use Map for that. Something like: (its "pseudo-code" - may contain spelling mistakes or something, just to show You the idea)
#Configuration
#ConfigurationProperties(locations = "classpath:mail.properties", prefix = "mail")
public static class MailConfiguration {
private Map<String, Object> mail = new HashMap<String, Object>();
public Map<String, Object> getMail() {
return this.mail;
}
}
Should do the work.
Regards,
All,
I have an instance of ProjectBudget class returned from a web method.
Ex:
[WebMethod()]
public ProjectBudget LoadBudget(int id)
{
ProjectBudget budget = BudgetManager.LoadBudget(id);
return budget;
}
The ProjectBudget class contains the following defintion:
public class ProjectBudget
{
public int Id = -1;
public long VersionNumber = -1;
public string QuoteNumber = "";
public string CurrencyCode = "";
public ProjectInfo Project;
public ClientInfo Client;
public readonly List<InventoryItem> Inventory = new List<InventoryItem>();
public readonly List<Staff> Staff = new List<Staff>();
public readonly List<CodeType> Departments = new List<CodeType>();
public readonly SerializableDictionary<string, string> Tasks = new SerializableDictionary<string, string>();
public ProjectBudget()
{
}
}
All public fields you see are serialized just fine with the exception of Tasks field, which is completely ignored by XML serializer. Since we all know by now that Dictionaries cannot be handled by XML serializer, I use a serializable dictionary (which is just a dictionary that implements IXmlSerializable) here but XML serializer decides to ignore it completely, i.e. the XML output does not contain any tasks and the generated proxy class doesn't have this field.
I need to figure out how to tell the XML serializer not to omit this field.
Btw, what is interesting is that a web method that returns SerializableDictionary works fine!
A very similar question as yours appears to have been asked already: Link.
Use DataContractSerializer or try explicitly implementing your getter (and setter), as per this link.
My Grails application has a large number of enums that look like this:
public enum Rating {
BEST("be"), GOOD("go"), AVERAGE("av"), BAD("ba"), WORST("wo")
final String id
private RateType(String id) {
this.id = id
}
static public RateType getEnumFromId(String value) {
values().find {it.id == value }
}
}
If I have a command object such as this:
class MyCommand {
Rating rating
}
I would like to (for example) automatically convert a request parameter with value "wo" to Rating.WORST.
The procedure for defining custom converters is described here (in the context of converting Strings to Dates). Although this procedure works fine, I don't want to have to create a class implementing PropertyEditorSupport for each of my enums. Is there a better alternative?
I found a solution I'm pretty happy with.
Step 1: Create an implementation of PropertyEditorSupport to convert text to/from the relevant Enum
public class EnumEditor extends PropertyEditorSupport {
private Class<? extends Enum<?>> clazz
public EnumEditor(Class<? extends Enum<?>> clazz) {
this.clazz = clazz
}
public String getAsText() {
return value?.id
}
public void setAsText(String text) {
value = clazz.getEnumFromId(text)
}
}
Step 2: Define a class that registers EnumEditor as a converter for the various enum classes. To change the list of enum classes that are bindable by id, just modify BINDABLE_ENUMS
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
private static final String REQUIRED_METHOD_NAME = 'getEnumFromId'
// Add any enums that you want to bind to by ID into this list
private static final BINDABLE_ENUMS = [Rating, SomeOtherEnum, SomeOtherEnum2]
public void registerCustomEditors(PropertyEditorRegistry registry) {
BINDABLE_ENUMS.each {enumClass ->
registerEnum(registry, enumClass)
}
}
/**
* Register an enum to be bound by ID from a request parameter
* #param registry Registry of types eligible for data binding
* #param enumClass Class of the enum
*/
private registerEnum(PropertyEditorRegistry registry, Class<? extends Enum<?>> enumClass) {
boolean hasRequiredMethod = enumClass.metaClass.methods.any {MetaMethod method ->
method.isStatic() && method.name == REQUIRED_METHOD_NAME && method.parameterTypes.size() == 1
}
if (!hasRequiredMethod) {
throw new MissingMethodException(REQUIRED_METHOD_NAME, enumClass, [String].toArray())
}
registry.registerCustomEditor(enumClass, new EnumEditor(enumClass))
}
}
Step 3: Make Spring aware of the registry above by defining the following Spring bean in grails-app/conf/spring/resources.grooovy
customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
So the default Databinding binds on the Enum name and not a separately defined property of the Enum. You can either create your own PropertyEditor as you have mentioned or do a work-around similar to this:
class MyCommand {
String ratingId
Rating getRating() {
return Rating.getEnumFromId(this.ratingId)
}
static constraints = {
ratingId(validator:{val, obj -> Rating.getEnumFromId(val) != null })
}
}