Domain Objects to map - java

We are building a micro-service REST api in groovy as part of a more complex application. This service would only just be a simple CRUD operations.
We are using groovy and on a GET we need to pull a record from the database ( mongodb ), and return the object after changing the format of some fields ( for backward compatibility ), something on these lines:
def object = collection.findOne(query)
object.field3 = object.field2.collect { [..]}
return object
I am not very experienced in groovy or java ( I worked more extensively on ruby/python/clojure ), but I would normally have a domain object:
class Foo {
String _id
String field1
Array field2
Map toMap() {
[field1: field1, field3: field2.collect {}, field2: field2]
}
}
and then just go
foo = new Foo(objectMapFromDb)
foo.toMap()
and some of the benefits that I see by using this approach is that I can look at the domain object and have an idea of what the structure of the object in the database is, I can get some type safety if I want to but more importantly ( and that's what drove my decision ) is that the code for converting the map is encapsulated in a function and can be easily re used in other part of the project
A more senior developer questioned this approach mentioning YAGNI and stating that domain objects are too complex, and reverted back to just changing changing the map as above.
I am a bit puzzled, I tried to look around for information about avoiding domain objects but I can't find anything similar to that ( I have looked at the anaemic domain model, but this seems to take it to the extreme ). About yagni I don't feel it applies in this case.
I personally don't see anything terribly wrong with that, for a simple application seems like a fine solution, but the novelty of this approach really stimulate my curiosity.
Any thought on this? Am I missing something?
Thanks

Related

DMN - matching a Java enum by a FEEL expression

I have a Java enum as an input in a DMN decision table. The DMN call is embedded directly in the Java app. So take some enum:
public enum Foo {
ONE, TWO
}
I pass an instance of this enum as an input - dmnContext.set("Foo", foo);
I hoped to be able to set a decision table input for foo of type string, and have a rule that matched "ONE". However, this doesn't work, because there is no POJO-String conversion. In the Java code, I could store foo as a String and validate it against the enumerated values (i.e. check foo is in the set ["ONE", "TWO"]), but this will complicate other parts of the application.
How can I achieve this while still using an enum type?
Please refer to this existing JIRA record comment section, for the explanation about:
why you are experiencing that behaviour
and why you should convert your Java-enum to the expected DMN type (which I guess) is a FEEL:string , and not an enum
You can use Jackson to achieve this, instead of resorting to custom code or DMN model modification.
Don't hesitate to Subscribe to the JIRA linked above, as we're hoping of making that work out-of-the-box; but is not trivial since the DMN RTF is thinking about introducing Enumerations directly in DMN eventually, so we need to take into account today what might happen tomorrow.
Since you are linking to Red Hat Product documentation, a reminder that you are strongly encouraged to open a Customer Portal ticket at https://access.redhat.com/support/cases/#/ if you have a Subscription.
I will appreciate your feedback following there references/pointers and I hope those helps

Use entity method as MapStruct source

Background
We are currently implementing an application using hexagonal architecture. Our REST API DTOs are mapped to our entities via MapStruct. This works fine. (Though, it would be much nicer if MapStruct would have support for hierarchical structures.)
Problem
However, we are facing a problem which is best described by the following example:
Consider you have an entity Person that stores the date of birth. Now, this
entity has a method which might be called int calculateAge().
The REST API's PersonDto will get an attribute int age.
Now, we want MapStruct to generate this mapping for us. Our approach was to try to configure #Mapping(target = "age", ...) to use the int calculateAge() method as source, but we did not succeed.
Believing this might be a straightforward application of MapStruct, we were quite disappointed to not come up with a clean solution after searching on this topic for hours.
Solutions
We found two solution approaches that work, but are (in our opinion) not really maintainable:
Use #Mapping(expression = "java(...)")
Use #AfterMapping to post process the constructed DTO and implement the required mappings in the annotated method
Question
Is there a cleaner way to achieve our goal, something which might look like this #Mapping(sourceMethod = "calculateAge", target = "age)?
Is there a cleaner way to achieve our goal, something which might look like this...
No, there isn't as of the MapStruct latest stable version (1.4.1.Final) of time of writing this answer. You have basically two choices which heavily depends what exactly and how you want to map the fields. I describe shortly in what case each solution is suitable for:
The first solution using expression introduces the problem the methods are hardcoded in the annotation. I prefer this solution only in the case of simple format conversions or calculations without calling a custom method (only from the existing Java API). Anyway, even with your proposed solution it would be still hardcoded. The syntax is the only thing that changes. There is effectively no difference in terms of maintainability:
#Mapping(target = "age", expression = "java(...)") // current API
#Mapping(sourceMethod = "calculateAge", target = "age") // hypothetical
Feel free to request for such feature. This solution in any case also requires imports within the mapper (#Mapper(imports = Another.class)) as well as the "hypothetical" one.
The annotation #AfterMapping is useful in case of more complex transformations and calculations. It's not as clean as a single annotation call and in fact you still write the mapping manually, however, it brings more control over the called methods which the IDE highlights before the compilation (at least you don't need an additional IDE-specific plugin). I'd go for this solution in case I need to call my custom methods and logics.
From what I've seen, Mapstruct relies on standard getters and setters. If you want to use a specific method then Mapstruct does work with #qualifiers, but I don't think the method can be in the entity. From my experience the best solution is to use #AfterMapping, as you mentioned.

Java Android: How to use Predicate<T> and Room together to retrieve specific elements from a database?

I'm coming from a C# background and trying to implement an Android App. In .Net C#, retrieving specific data from a database is relatively easy using Entity Framework and Linq, my usual approach is something like this (simplified for clarity):
public IQueryable<T> GetElements<T>()
where T : class, IDBKeyProvider
{
return this.db.Set<T>().Where(e => e.Dbstate == (int)DBState.Active);
}
This method call results in a generic IQueryable and later on, I can use the power of deferred execution and expression trees to specify exactly which elements I want using a predicate, loading only desired elements in memory.
This is something I would very much like to go for in my Android App, however, I'm not exactly sure how I could arrive at a similar result, if I can at all.
I looked into some Java Predicate examples, which seemed promising and I also found Room to be delightfully familiar. My problem, however, is that I cannot make my queries fully customizable due to the fact that, Room still needs some hard-coded info about my db (original here):
#Dao
public interface MyDao {
#Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
}
I could perhaps extract the relevant pieces of information with Java Reflection from the predicate parameter, but I feel this to be a hack rather than a proper solution.

Dynamic Fields and/or Artificial Methods

I work with a dynamic Dataset model, which (in short) takes in attributes and stores them in a Map like this...
Dataset dataset = new Dataset();
dataset.setAttribute("name", "value");
...for later recovery, like this...
String value = dataset.getAttribute("name");
...and that has worked wonderfully for my purposes. But now I'm in a place where I'd like to use a templating engine to dynamically generate HTML. In the template, it's not ideal for me to do a lot of ${dataset.getAttribute("name")}. It would be rather nice if I could create artificial methods whenever something was added to a Dataset. For instance, if I did this...
dataset.setAttribute("name", "value");
...I'd like to be able to retrieve it like this...
String name;
name = dataset.name;
//or
name = dataset.getName();
...but so far I haven't been able to pull it off. What approach might I take here? Is it even doable?
Edit:
I understand that Velocity offers Property Lookup Rules to try to resolve dataset.name to dataset.get("name"), and that's great, but I need to know how to achieve this in the case that Velocity isn't the target as well.
See http://velocity.apache.org/engine/releases/velocity-1.5/user-guide.html#propertylookuprules
If your method was named get(String attribute) rather than getAttribute(String attribute), you could use the same syntax as for regular properties. So, either refactor your class, or add an additional get method that does the same thing as getAttribute, or transform your object into a Map, which has a get method.
In the past I have generated POJOs dynamically with Objectweb's ASM. This has the benefit that the underlying fields are type safe and much more efficient (esp for privative values)
You can use Dynamic Spring proxies with AOP technology or CGLib proxies. AOP could be used to describe getters like this : execution(public * com.bla.YourClass.get*())")
From what I've seen, it's fairly common for template engines for Java to support both
getters/setters of the form getAttribute, and
implementation of the Map interface
Before you spend too much time looking for a more generic solution (assuming the above won't be supported like it is in Velocity), it's probably worth taking a look at the other engines to see if any of them don't support it. If all your possible targets do, then you're probably fine relying on it.
I'm a big fan of making sure you actually have a problem before you spend the time to solve it.

Infinispan MVCC with "put"

I wanted to use Infinispan today in a sort of probably unfamiliar matter.
I want to save a Variable, let's call it x a couple of times in the cache - while being able to adress it as X.
Plain, old MVCC. However, it seems that infinispan uses MVCC on the backend - but I wasn't able to use it in my little test-application.
This is the corresponding code:
acTest.put("test", "blubber", 0, TimeUnit.MILLISECONDS );
acTest.put("test", "nothing", 0, TimeUnit.MILLISECONDS );
if( acTest.containsKey("test") )
{
Object foo = acTest.get("test"); // don't know how to get the "blubber" out of that
String name = (String) test2.get("name");
System.out.println(name);
}
Sure enough, acTest contains the key - but I was not able to adress the value "blubber" of that key - when I higher the numerical value of "nothing" foo holds "nothing" ... but I want to get the first version of "foo" - hence "blubber"
I want to be able to adress the different versions of test. I think that I can create different versions of "test" with the different parameters in the put operation - however eclipse has absolutely no documentation for that matter ...
Could somebody help me?
Infinispan uses MVCC in it's container for internal purposes, this is currently not a feature exposed via user API, besides via writeSkewCheck.
In version 5.1 the API will expose Optimistic locking, which might be useful for some use cases needing to take advantage of the MVCC capabilities, but you still won't be able to extract a previous value.
You could use AtomicMap to store multiple values, or use custom key objects containing the version, building what you need on top of Infinispan's API.
DeltaAware is another option, but it's a low-level interface meant for experts.

Categories