Mapping Java Optional with DynamoDBMapper annotations - amazon-dynamodb

Is there a clean way to map Optional fields with DynamoDBMapper, for both basic types and arbitrary/custom objects?
I believe one option would be to implement DynamoDBTypeConverter for optionals of basic types (Optional<String>, Optional<Integer>, etc). But, in addition to being a bit dirty, this would not work for custom objects.
I am looking for some sort of "chaining" behaviour of converters, where the default converter is applied first and the result wrapped in case of optional fields.
Is there a way to specify this behaviour?
#DynamoDBTable
public class MyModel {
#DynamoDBAttribute
private Optional<String> someStringField;
#DynamoDBAttribute
private Optional<AnotherModel> someAnotherModelField;
...
}
#DynamoDBDocument
public class AnotherModel {
}

For what you want to do, I believe the custom converters is the proper way.
Create a class for example:
class SomeAnotherModelOptionalConverter implements DynamoDBTypeConverter<String, Optional<AnotherModel>> {
#Override
public String convert(Optional<AnotherModel> optional) {
// your conversion from Optional attribute to String DynamoDB attribute
}
#Override
public Optional<AnotherModel> unconvert(String s) {
// your conversion from String DynamoDB attribute to Optional
}
}
Then on your attribute, you add the following tag:
#DynamoDBAttribute
#DynamoDBTypeConverted(converter = SomeAnotherModelOptionalConverter.class)
private Optional<AnotherModel> someAnotherModelField;
Anyways, I would not use an Optional as a field in a class. Instead I would create a getter that has and Optional as a return.
private AnotherModel someAnotherModelField
...
Optional<AnotherModel> getSomeAnotherModelField(){
return Optional.ofNullable(someAnotherModelField);
}
Let me know if that works for you!

Related

How to make a field set-able only inside extension method

Hello i want to be able to set the a of a field of an object only in an extension method. I would want that this field to either be completelely private , or be just get-able from outside:
public class Myclass
{
private int Value{get;set;}
}
public static class Ext
{
public Myclass SetValue(this Myclass obj,int val)
{
this.obj.Value=val;
return obj;
}
}
As you can see in the above example , i have to declare Value public to be able to access it inside the extension , i would be ok with that if i could make the variable only get-ablefrom outside.
I need this functionality because i want to develop something like a fluent api , where you can only set some variables using the extension.
ex:
a=new Myclass();
a.SetValue1(1).SetValue2(2);//--some code //--a.SetValue3(3);
It sounds like you're using the wrong tool for the job, extension methods don't have access non-public members.
The behavior you want is restricted to instance methods or properties. My recommendation is to add an instance method to the class.
If that doesn't persuade you, then you can instead use reflection to update the private instance variable:
public static class Ext
{
public Myclass SetValue(this Myclass obj,int val)
{
var myType = typeof(Myclass);
var myField = myType.GetField("Value", BindingFlags.NonPublic | BindingFlags.Instance);
myField.SetValue(obj, val);
return obj;
}
}
Please note that this has the following gotchas:
There are no compile time checks to save you if you decide to rename the field Value. (though unit tests can protect you)
Reflection is typically much slower than regular instance methods. (though performance may not matter if this method isn't called frequently)
you want it to do it with extension method but you cannot in this case.
Your best option is
public class Myclass
{
public int Value{get; private set;}
public Myclass SetValue(int val)
{
this.Value=val;
return obj;
}
}

Mapper decorator not getting compiled

Mapper decorator for my mapper is not getting compiled.Mapper is getting compiled, but not the decorator. Because, during the build I'm getting the type conversion error, even though I'm doing it in the mapper decorator. Is there anything more to add?
mapper code:
#Mapper
#DecoratedWith(OneMapperDecorator.class)
public interface OneMapper {
public TwoObject convertToTwoObject(OneObject one);
}
decorator code:
public abstract class OneMapperDecorator implements OneMapper {
private final OneMapper delegate;
public OneMapperDecorator (OneMapper delegate) {
this.delegate = delegate;
}
#Override
public TwoObject convertToTwoObject(OneObject one)
{
TwoObject two=delegate.convertToTwoObject(one);
two.setTotalFare(new BigDecimal(one.getPrice()));//string to bigdecimal conversion
return two;
}
}
The decorator is meant to augment the mapping not to replace it. MapStruct has no way of knowing that you are mapping your totalFare in the decorator. You have 2 options:
Define a custom mapping method
In your OneMapper you can add a default method that would perform the mapping (as the error says.
#Mapper
#DecoratedWith(OneMapperDecorator.class)
public interface OneMapper {
#Mapping(target = "totalFare", source = "price");
TwoObject convertToTwoObject(OneObject one);
default BigDecimal map(String value) {
return value == null ? null : new BigDecimal(value);
}
}
Ignore the mapping
In case you want to do the mapping in your decorator then you need to tell MapStruct to not map it.
#Mapper
#DecoratedWith(OneMapperDecorator.class)
public interface OneMapper {
#Mapping(target = "totalFare", ignore = true);
TwoObject convertToTwoObject(OneObject one);
}
One advise from me if you are using your delegate only to map extra fields I would either add custom methods or use #AfterMapping and #BeforeMapping to handle that.

Is there a way to customize the ObjectMapper used by Spring MVC without returning String?

I have a graph of objects that I'd like to return different views of. I don't want to use Jackson's #JsonViews to implement this. Right now, I use Jackson MixIn classes to configure which fields are shown. However, all my rest methods return a String rather than a type like BusinessCategory or Collection< BusinessCategory >. I can't figure out a way to dynamically configure the Jackson serializer based on what view I'd like of the data. Is there any feature built into Spring to configure which Jackson serializer to use on a per-function basis? I've found posts mentioning storing which fields you want in serialized in thread-local and having a filter send them and another post filtering based on Spring #Role, but nothing addressing choosing a serializer (or MixIn) on a per-function basis. Any ideas?
The key to me thinking a proposed solution is good is if the return type is an object, not String.
Here are the objects in my graph.
public class BusinessCategory implements Comparable<BusinessCategory> {
private String name;
private Set<BusinessCategory> parentCategories = new TreeSet<>();
private Set<BusinessCategory> childCategories = new TreeSet<>();
// getters, setters, compareTo, et cetera
}
I am sending these across the wire from a Spring MVC controller as JSON like so:
#RestController
#RequestMapping("/business")
public class BusinessMVC {
private Jackson2ObjectMapperBuilder mapperBuilder;
private ObjectMapper parentOnlyMapper;
#Autowired
public BusinessMVCfinal(Jackson2ObjectMapperBuilder mapperBuilder) {
this.mapperBuilder = mapperBuilder;
this.parentOnlyMapper = mapperBuilder.build();
parentOnlyMapper.registerModule(new BusinessCategoryParentsOnlyMapperModule());
}
#RequestMapping(value="/business_category/parents/{categoryName}")
#ResponseBody
public String getParentCategories(#PathVariable String categoryName) throws JsonProcessingException {
return parentOnlyMapper.writeValueAsString(
BusinessCategory.businessCategoryForName(categoryName));
}
}
I have configure the serialization in a MixIn which is in turn added to the ObjectMapper using a module.
public interface BusinessCategoryParentsOnlyMixIn {
#JsonProperty("name") String getName();
#JsonProperty("parentCategories") Set<BusinessCategory> getParentCategories();
#JsonIgnore Set<BusinessCategory> getChildCategories();
}
public class BusinessCategoryParentsOnlyMapperModule extends SimpleModule {
public BusinessCategoryParentsOnlyMapperModule() {
super("BusinessCategoryParentsOnlyMapperModule",
new Version(1, 0, 0, "SNAPSHOT", "", ""));
}
public void setupModule(SetupContext context) {
context.setMixInAnnotations(
BusinessCategory.class,
BusinessCategoryParentsOnlyMixIn.class);
}
}
My current solution works, it just doesn't feel very clean.
"categories" : [ {
"name" : "Personal Driver",
"parentCategories" : [ {
"name" : "Transportation",
"parentCategories" : [ ]
} ]
}
Oh yes, I'm using:
spring-boot 1.2.7
spring-framework: 4.1.8
jackson 2.6.3
Others listed here: http://docs.spring.io/spring-boot/docs/1.2.7.RELEASE/reference/html/appendix-dependency-versions.html
In the end, the only process that met my needs was to create a set of view objects which exposed only the fields I wanted to expose. In the grand scheme of things, it only added a small amount of seemingly unnecessary code to the project and made the flow of data easier to understand.

Finding all Classes beloning to a superclass using Java 7

I'm looking for a way in java to find all classes that belongs to a certain superclass, and within that class refer to a static string with a known name (using reflection?);
public class Bar
extends ObjectInstance
{
public final static String Name = "Foo";
// more
}
From the example; there are n-occurences of classes that extend from ObjectInstance, and from all, i need the value of Name. The classes i am refering to are generated so i know for sure that there is a Name element that i can refer to, but i have no access to the generation sourcedata.
Perhaps the same question as How do you find all subclasses of a given class in Java?
This backs up my initial feeling that this can only be done like IDEs do it: by scanning everything down the tree, building your relationships as you go.
No Way.
One failing solution:
publc abstract class ObjectInstance {
public abstring String name();
private static Map<String, Class<? extends ObjectInstance> klasses =
new HashMap<>();
protected ObjectInstance() {
classes.put(name(), getClass());
}
Only collects instantiated classes! So fails.
With the idea to have the name provided by a function with return "foo";.
Collecting the class.
There are two unsatisfactory solutions:
The other way around: use the name as a factory pattern:
enum Name {
FOO(Bar.class),
BAZ(Baz.class),
QUX(Qux.class),
BAR(Foo.class);
public final Class<ObjectInstance> klass;
private Name(Class<ObjectInstance> klass) {
this.klass = klass;
}
}
Maybe as factory to create instances too.
Using a class annotation, and have a compile time scanning:
#ObjectInstanceName("foo")
public class Bar extends ObjectInstance {
}
How to apply this to your case: experiment.
There would be a more fitting solution of using your own ClassLoader, but that is far too over-engineered.

How does versioning work with Flex remote objects and AMF?

Suppose I use the [RemoteClass] tag to endow a custom Flex class with serialization intelligence.
What happens when I need to change my object (add a new field, remove a field, rename a field, etc)?
Is there a design pattern for handling this in an elegant way?
Your best bet is to do code generation against your backend classes to generation ActionScript counterparts for them. If you generate a base class with all of your object properties and then create a subclass for it which is never modified, you can still add custom code while regenerating only the parts of your class that change. Example:
java:
public class User {
public Long id;
public String firstName;
public String lastName;
}
as3:
public class UserBase {
public var id : Number;
public var firstName : String;
public var lastName : String;
}
[Bindable] [RemoteClass(...)]
public class User extends UserBase {
public function getFullName() : String {
return firstName + " " + lastName;
}
}
Check out the Granite Data Services project for Java -> AS3 code generation.
http://www.graniteds.org
Adding or removing generally works.
You'll get runtime warnings in your trace about properties either being missing or not found, but any data that is transferred and has a place to go will still get there. You need to keep this in mind while developing as not all your fields might have valid data.
Changing types, doesn't work so well and will often result in run time exceptions.
I like to use explicit data transfer objects and not to persist my actual data model that's used throughout the app. Then your translation from DTO->Model can take version differences into account.

Resources