Is there an easy way to do the following, using the Play! framework and hibernate?
I have a class Article with generic data like pubDate, author etc. etc.
In the class there are two fields, title and content, which needs however be provided in different languages. All the other data, inclusing the id should be the same.
The server side of the system will select according to the settings of the client which title/content to push out, either the default language or the language of preference when available. Beacuse of the synchronisation it is important to keep the article id the same for all linked languages.
Currently I have the content and the title in the class, and am wondering if I should either subclass the baseclass which has all the basic info and add the content/title that way, our leave the content/title of the default language in the baseclass and optionally add the content/title of additinoal languages as an seperate class (and on pushing it to the client replace it the content transciently in the baseclass if required).
What would be the best way to approach this problem?
I wouldn't subclass, because language preference is a rendering issue. There's no different behavior by Article just because the content is in a different language.
I'd have the Article class include title, content, and language. The primary key would now be article id and language. When a user asked for a particular title I'd query for it using the article id and either their language preference or the default if none was provided.
I would implement language specific data in a separate table if it is not easy to use i18n such this cases.
You could have Article and ArticleDetail models. In this model you have one Article and many language instances of this Article.
#Entity
public class Article extends Model {
private Author author;
private Date pubDate;
...
}
#Entity
public class ArticleDetail extends Model {
#MayToOne
private Article
private String languageCode;
private String title;
private String content;
...
}
So if you want to select a content just call ArticeDetail.find("article.id=? and langCode=?", articleId, langCode)
Related
Assuming I have a class User with many fields:
public class User {
public Integer id;
public String name;
public String username;
public Integer age;
public Address address;
public String phoneNumber;
public String email;
}
But I will not always need all User attributes in frontend. Each screen needs only some of User's fields. Is it a good practice to make DTO classes for each screen, since they access different attributes? Like this:
class UserToScreenADTO implements Serializable {
public String name;
public String email;
}
class UserToScreenBDTO implements Serializable {
public String phoneNumber;
public Address address;
}
class UserToScreenCDTO implements Serializable {
public Integer id;
public String username;
public String email;
}
I would create just one DTO class but e.g. pass to its constructor
the list of the fields which I want to be pulled and set by the backend.
All other fields will be null.
The list of fields will be passed in by the front-end.
I find this approach pretty flexible/dynamic.
It also avoids multiple classes to maintain.
I don't know if this approach matches any best practices or enterprise patterns
but creating multiple DTO classes definitely sounds worse.
Using "just" one DTO or the entity directly comes with a high cost that you usually only pay later, so I would recommend anyone to create a DTO per use case just like you did here.
Here are some of the reasons/costs for this:
If the user of the API sees accessors for state that isn't loaded this will trigger lazy loading which will either result in bad performance or lazy initialization exceptions. If objects are passed through a session, you might lose the context how the object came to be, so you might not always be able to tell which state is loaded.
It might be inefficient to load all data all the time. If you have some text columns that contain lots of data this has to be transferred over the wire and materialized as Java Objects etc. If you don't use the data, it's just pointless to load it at all. One might say this is negligible, but it depends on your use case. The worst that can happen? The DBMS does a full table scan or a less efficient index scan rather than index only scan because you instruct the DBMS to load the value for a column.
Not all the state that you want to provide for a client should be in the relational representation. If you do aggregations or use expressions for e.g. concatenating columns together, you need a DTO.
Having said that, this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(User.class)
public interface UserToScreenADTO extends Serializable {
String getName();
String getEmail();
}
#EntityView(User.class)
public interface UserToScreenBDTO extends Serializable {
String getPhoneNumber();
Address getAddress();
}
#EntityView(User.class)
public interface UserToScreenCDTO extends Serializable {
Integer getId();
String getUsername();
String getEmail();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
UserToScreenADTO u = entityViewManager.find(entityManager, UserToScreenADTO.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Since OP said that the system is used from the same frontend and in the same context, I would consider it bad practice and not recommend using different DTOs.
Reasoning:
Modern frontends normally manage a store of all entites received by the backend. So the frontend can look up entities in the store and - depending on caching policies - load them from the store rather than requesting them from the server. Thus, instead of fetching users part-by-part, the user is transmitted once. This can be further improved by using ETags. While the usage of Etags will hardly improve latency, it can improve network load since the response to a matching ETag is a 304/Not Modified without a body (!) rather than a 200/OK with body. While ETags can be used with many Dto-Objects, more (partial) updates might occur. If, for example, the email and the phone number of a user changes, and the frontend first requests the UserToScreenADTO, it would get a response body that - among other things - contains the new email. When it then later requests a UserToScreenBDTO, it would - again - receive a response body containing the new phone number. With only one DTO, the frontend will receive one updated representation on the first request, and all successive request (made with the matching ETag) will result in a 304/Not Modified.
Furthermore, more classes normally mean higher complexity. Thus, I would recommend to keep the number of classes reasonably small. If using an ETag is not wanted and/or the frontend does not keep a store of server-sent entities, I would recommend the approach described in peter petrov's answer.
The representation should only change if the context changes. If the representations differ drastically between, for example, a user-frontend and an admin-frontend, then different DTOs may be justified.
I apologize in advance because this question is almost a bit silly. Nonetheless, I can't come up with a good solution myself, so I thought it still worthwhile to ask.
What does one do when the Representation object and the Domain object should have the same name? The DDD Sample doesn't really address the representation layer, so I was unable to find help there. An Account class works as well as any to illustrate:
package com.mycompany.myproduct.representation;
public class Account {
private String uuid;
private String accountNumber;
// etc
#JsonCreator
public Account(#JsonProperty('uuid) String ....
}
Maybe this system has a convention to return data as a String whenever possible. But I like having all the Json annotations here. While that means XML isn't really supported, that seems okay for now, though more flexibility there would be nice. Then in the Domain layer there might be another class like this:
package com.mycompany.myproduct.domain.model;
import java.uti.UUID;
public class Account extends Entity {
private UUID id;
private BigDecimal accountNumber;
// ... business logic, etc
}
If both of these datatypes are named the same the code will be ugly/unsupportable in the cases where they eventually have to meet. As part of the Ubiquitous Language, it seems like the Domain Layer HAS to have the Account Class. But the outside world talks in terms of the representation object. If that is their language, why should they use anything different?
Since these two classes are in separate namespaces, you could keep to the same name. But as you mentioned, this can get ugly and is certainly misleading.
I strongly advocate for pure, "real-world" naming in your domain layer. Account is a great example. Your rich Account domain entity, with its state, behaviour and invariants, represents an account in the real world.
Identifier naming outside of your domain should perhaps be more explicit to the context in which it is used. For example, I generally use the following:
AccountModel for an API response model.
AccountTable for a ORM class.
AccountDto for some transfer object (although please do try avoid DTOs!)
Everyone has their own standard. I believe the important thing to be consistency, especially when you are working with a team.
This question is not concerning the exact specifics of how to serialize a Java object to a JSON representation, but rather a scalable and testable pattern for serializing Java objects to JSON. The system in which I'm maintaining has the notion of varying levels of granularity with regards to serialization of objects. For example, the system has a concept of a Project. A Project has the following fields:
Name
Description
Owner
List of tasks
Change history
Other metadata
When serializing a list of Projects, it's useful to only return the "summary" information:
Name
Description
Owner
Omitting the more detailed stuff. However, when request a single Project, a "detailed" view is returned which includes everything. Most objects in the system have this notion of a summary and a detail view, but I'm finding that in most cases, I'm either returning too much or too little information.
To handle which attributes are returned for which view, I've simply annotated the class, and described a summary and a detail view:
#Json(summary = { "name", "description", "owner" },
detail = { "name", "description", "owner", "tasks", "changes", ... }
class Project {
private String name;
...
}
This works decently, but as I mentioned above, I find in most cases, I'm either returning too much or too little. I would be interested to see what kind of patterns exist out there for a flexible approach to getting the data I need. Am I doing it wrong if I'm finding that I'm needing to return different representations of my data? Should I pick a set number of object representations and stick with that? Thanks for your help.
You could use subclassing with an automatic serialisation framework. For example using JAXB (which supports both JSON and XML):
class DetailSummary {
public #XmlElement String name;
public #XmlElement String description;
public #XmlElement String owner;
}
class Detail extends DetailSummary {
public #XmlElement List<Task> tasks;
...
}
This approach allows multiple levels of detail but forces you to use your classes as simple records.
I am trying to learn UML concepts and their application in Java programming. I am aware of association, shared aggregation and composition concepts. What I am confused about is how they are applied to a particular scenario. e.g. if we have a set of three classes: Book, Author and Publisher, how can we apply these concepts.
Book.java
class Book {
private String ISBN;
private String category;
private Publisher publisher;
private ArrayList<Author> authors;
}
Author.java
class Author {
private String authorName;
private String phoneNo;
private String email;
private ArrayList<Book> books;
}
Publisher.java
class Publisher {
private String publisherName;
private String publisherAddress;
private ArrayList<Book> books;
}
Are these mere associations? Can we say that the relation between Publisher and Book is of shared aggregation? What about the many-many relation between Book-Author?
To me it appears that Publisher-Book is a shared aggregation, Book-Author is a simple association. And if there will be a Chapter class, related to a Book, that would be composition. Am I right in my understanding?
Association, Aggregation, and Composition are all "has a" relationships.
Association means simply that two classes are associated with each other, but instances of each can exist independently of one another. Your example shows no simple associations.
Aggregation is a special association where one class houses a collection of another class. Authors have many Books, Publishers have many Books, etc.
Composition is a special aggregation that implies a strong life-cycle tie. In other words, the composed class generally cannot exist outside of the parent. For example, A Map.Entry cannot exist without the Map. You have no examples of this above.
You should also be aware that "composition" as it pertains to UML is much stricter/narrower than in Java.
According to the UML Superstructure Specification, v2.4.1 (read below), "share aggregation" is not specially defined in UML. So whether it is shared or not depends on the model and whether it is composite or not depends on how the existences are managed.
"AggregationKind is an enumeration of the following literal values:
none - Indicates that the property has no aggregation.
shared - Indicates that the property has a shared aggregation.
composite - Indicates that the property is aggregated compositely, i.e., the composite object has responsibility for the existence and storage of the composed objects (parts).
Semantic Variation Points - Precise semantics of shared aggregation varies by application area and modeler."
While there is a many-to-many association between Book and Author, there is a many-to-one association between Book and Publisher.
In your Java classes you have been using two pairs of mutually inverse reference properties Book::authors and Author::books as well as Book::publisher and Publisher::books. This is the pattern for implementing bi-directional associations.
For more about associations, see Section 1 of my tutorial about associations.
I've started learning GWT about a week ago and here's the question I can't answer for sure.
Here's the server-side:
// business object - has logic
interface Article {
String getTitle(); // lazy
void setTitle();
String getText(); // lazy
void setText();
Set<Comment> getComments(); // lazy
}
// also has logic
interface Comment { ... }
I need to somehow create a GWT widget to visualize Article. Passing Article won't work, since it's not serializable and moreover, it has some BL. So, there are 2 ways:
The first one is to use DTOs like:
class ArticleDTO implements Serializable {
public int articleId;
public String title;
public String text;
}
class CommentDTO implements Serializable {
public int commentId;
public int articleId;
public String commentText;
}
The I'll have to implement a repository logic in my GWT RPC service:
class MyRPCRepository ... {
ArticleDTO getArticle(int id);
void saveArticle(ArticleDTO article);
void deleteArticle(ArticleDTO article);
...similar things for comments here...
}
The second way is to use DAOs:
class ArticleDAO implements Serializable {
private transitional MyRPC rpc;
private int articleId; // only this one is serializable
public ArticleDAO(MyRPC rpc, int articleId) { ... }
public String getTitle() {
// i know it would require more code in real
return rpc.getArticleTitle(articleId);
}
...
}
I like the first one, because it's really stupid. I like the second one because it's quite intellectual. Which one should I choose to make the code easier to understand and maintain?
In projects I've worked on, people seem to differ a lot in their opinions about the best approach to take with problems like this. There are pros and cons for both. The DTO approach is now supported by GWT in an API called RequestFactory, and is advertised as an alternative to "standard" GWT RPC usage (your DAO approach). You gain performance and integration with GWT's data binding framework, and the cost of maintaining the DTOs. I think it's a good trade-off, but for small projects it might be overkill.
Typically DAOs are objects that determine data access methods of your system, while DTOs define data that is used by DAOs. So your first method is quite good but it is actually DAO/DTO method with MyRPCRepository being actually DAO (Data Access Object).
Second method is totally weird to my taste. It is some kind of service that allows you to access some pieces of your data and yet it retains some state (usually you want DAOs to be stateless).
So I vote for the first method, but repository should probably be called ArticleDAO and similar DAOs would be there for other data objects.
The question to ask is "how do you intend to use any of the solutions?" Assuming you have a kind of table UI on the client side, where you always show articelId, title and text (knowing that you are describing a kind of "Online Forum" I can assume you don't show the text, but lets pretend I did not know that). Now, with a DTO you simply can transfer a bunsh (one page?) of objects to the client. That means the transfer is done in one chunk and there is only one request from the client to fullfill.
With your DAO approach (which I would not call DAO but "Service" in this case) you might still send a bunsh of objects in one request/response to the client, but a cascade of small requests to display title and text will come back from the client.
So the question to ask is: how does the user interact with your system? In your concrete example I always would transfer "id" and "title" and only use a second request/DAO approch for the text.
OTOH again, if only a few users are using the system (dozens or a few hundret) I would use the approach that is most easiest to develop or maintain.