I trying to find the distances along with the locations by using Spring Data Mongo GeoSpatial.
Following this https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.geo-near
GeoResults<VenueWithDisField> = template.query(Venue.class)
.as(VenueWithDisField.class)
.near(NearQuery.near(new GeoJsonPoint(-73.99, 40.73), KILOMETERS))
.all();
I tried
#Data
#NoArgsConstructor
#AllArgsConstructor
public class RestaurantWithDisField {
private Restaurant restaurant;
private Number dis;
}
#Data
#AllArgsConstructor
#NoArgsConstructor
#Document(collection = "restaurants")
public class Restaurant {
#Id
private String id;
private String name;
#GeoSpatialIndexed(name = "location", type = GeoSpatialIndexType.GEO_2DSPHERE)
private GeoJsonPoint location;
}
public GeoResults<RestaurantWithDisField> findRestaurantsNear(GeoJsonPoint point, Distance distance) {
final NearQuery nearQuery = NearQuery.near(point)
.maxDistance(distance)
.spherical(true);
return mongoTemplate.query(Restaurant.class)
.as(RestaurantWithDisField.class)
.near(nearQuery)
.all();
}
But in the result I am getting the below. If I don't set the target type and just collect the domain type I get all the other values but the distance.
Restaurant - RestaurantWithDisField(restaurant=null, dis=0.12914248082237584
Restaurant - RestaurantWithDisField(restaurant=null, dis=0.19842138954997746)
Restaurant - RestaurantWithDisField(restaurant=null, dis=0.20019522190348576)
Can someone please help me why I am unable to fetch the domain type value or how should I?
Thank you
The mapping fails to resolve restaurant in RestaurantWithDisField because the values within the result Document do not match the target entities properties.
You might want to use inheritance instead of composition here and let RestaurantWithDisField extend Restaurant, provide your own converter or just use Restaurant and rely on GeoResults holding a list of GeoResult that already include the Distance along with the actual mapped domain type - pretty much the same, that you've be modelling with RestaurantWithDisField.
Spring Data Mongo repository can generate the right query for you if you name it correctly and put the data into your domain POJO. I was able to find examples here - blocking or here - reactive.
interface RestaurantRepository extends MongoRepository<Restaurant, String> {
Collection<GeoResult<Restaurant>> findByName(String name, Point location);
}
From what I see, the (Reactive)MongoTemplate uses a GeoNearResultDocumentCallback to wrap the restaurant in a GeoResult. You may want to take a look there.
Related
I have REST API working, but I need a way to return all products within a certain category. Right now I'm using findSearchResultsByCategoryAndQuery by passing the category id and using a very generic query to get almost all the products in the category. What I really need is a method called findAllProductsForCategory which returns all products in the category.
I'm new to Broadleaf and REST API, can someone please guide me through how to extend CatalogEndpoint to get the functionality I need.
Althought broadleaf provides SQL injection protection (ExploitProtectionServiceImpl) I recommend you to use ProductDao.
Extend org.broadleafcommerce.core.web.api.endpoint.catalog.CatalogEndpoint or add in your implementation new method that utilize ProductDao
#Resource("blProductDao")
private ProductDao productDao;
#RequestMapping(value = "search/products-by-category/{categoryId}") //GET is by default
public List<Product> findSearchResultsByCategory(HttpServletRequest request, #PathVariable("categoryId") Long categoryId {
return productDao.readProductsByCategory(categoryId);
}
It's querying database with:
SELECT categoryProduct.product_id
FROM BLC_CATEGORY_PRODUCT_XREF categoryProduct
WHERE categoryProduct.category_id = :categoryId
ORDER BY COALESCE (categoryProduct.display_order,999999)
Or if you want to create your own dao
public class MyProductDaoImpl extends ProductDaoImpl implements MyProductDao {
public static final String QUERY = "SELECT categoryProduct.product_id " +
"FROM BLC_CATEGORY_PRODUCT_XREF categoryProduct " +
"WHERE categoryProduct.category_id = :categoryId";
#Override
public List<Product> meFindingProductsByCategory(String categoryId) {
Query query = em.createQuery(QUERY);
query.setParameter("categoryId", categoryId);
return query.getResultList();
}
}
You can choose if you are producing JSON or XML. Be sure that you have coresponding Product model for binding results
In my attempt to start learning about DDD, I began with a simple domain model that I will gradually build up over time. My domain in this instance is the usual order > order item in order to keep things simple and be able to add on later with invoices, etc. Here's what I have so far:
public class Order
{
private readonly IList<OrderItem> _orderItems;
public Guid Id { get; private set; }
public bool Completed { get; private set; }
public DateTime Created { get; private set; }
public IEnumerable<OrderItem> OrderItems
{
get { return _orderItems; }
}
public Order()
{
Id = new Guid();
Created = DateTime.UtcNow;
_orderItems = new List<OrderItem>();
}
public void AddOrderItem(int quantity, int unitCost)
{
var orderItem = new OrderItem(quantity, unitCost);
_orderItems.Add(orderItem);
}
public void CompleteOrder()
{
Completed = true;
}
}
public class OrderItem
{
public int Quantity { get; private set; }
public int UnitCost { get; private set; }
public OrderItem(int quantity, int unitCost)
{
Quantity = quantity;
UnitCost = unitCost;
}
}
I will eventually turn Quantity and UnitCost into value objects, but that isn't the important part here. As DDD preaches, we always want to protect our invariants, but I'm having a little trouble with one piece of that. From an Order, you can add a new OrderItem by calling the AddOrderItem() method and passing your quantity and unit cost.
My question now becomes what is to stop another coder from creating a new OrderItem with var orderItem = new OrderItem(1, 2)? The OrderItem constructor should probably have an Order order parameter since an OrderItem cannot exist without an Order, but again now that other coder could just call new OrderItem(new Order(), 1, 2)?
Am I missing something? Or is it just accepted that the team working on the model needs to understand the fundamentals of DDD?
Update
Thanks #theDmi, #guillaume31, #Matt as you all have provided some good points. I think it is pretty clear at this point that the repository's interface should be enough to make it clear that you can't do anything with an OrderItem created by itself. Setting the ctor for OrderItem to internal also helps to enforce this restriction as well, but it may not be needed. I plan to see what happens with or without the internal ctor. Ultimately, the reason I accepted #guillaume31's answer is the comment about the bidirectional relationships. That makes a lot of sense and I have encountered this issue in the past with EF for example, so I like the idea of keeping it unilateral as well.
"An OrderItem cannot exist without an Order" is not really an invariant. Well at least it's not an invariant in the Order aggregate. By definition, invariants only look at things that are inside one aggregate (or span across multiple ones), not things that wander around outside an aggregate.
The OrderItem constructor should probably have an Order order
parameter since an OrderItem cannot exist without an Order
I wouldn't model it that way, because
Bidirectional relationships between entities are not recommended. It can lead to synchronization problems (A points to B but B points to something else), it's better to have unidirectional relations if you can.
By doing that, your ultimate goal is to put a constraint on what's happening outside an Aggregate, which is not really the point of DDD, and, as other answers have shown, dispensable. All changes in a DDD system go through an Aggregate and a Repository.
When working with DDD, all attempts to change the state of the system run through a repository, because you need to retrieve the aggregate you want to work on first. So even if someone creates objects that make no sense outside of a certain entity, they will not be able to do anything useful with it.
Regarding this problem, DDD has even advantages over CRUD-based systems: It leads to a high discoverability. First, the repository interface tells you what you can load. Then you get an aggregate, which in turn offers operations that modify the aggregate in a meaningful way.
Let's say I want to create action web site where members would be able to bid for items. To model this domain I have three classes: Member, Item and Bid.
My brainstorming would go something like this:
Item can contain multiple bids
Bid is associated with one Item and one Member
Member can contain multiple bids
Member and Item can exist without bid instance
Bid instance can't exist without both Member and Item
Considering all this it is obvious that since Member and Item objects are independent we can consider them aggregate roots. Bid will be part of one of these aggregate. That is clear but what is confusing to me right now is which aggregate root should I choose? Item or Member?
This is example from Pro ASP.NET MVC 3 Framework book by Apress, and the way they did is like following:
Which gives following code:
public class Member
{
public string LoginName { get; set; } // The unique key
public int ReputationPoints { get; set; }
}
public class Item
{
public int ItemID { get; private set; } // The unique key
public string Title { get; set; }
public string Description { get; set; }
public DateTime AuctionEndDate { get; set; }
public IList<Bid> Bids { get; set; }
}
public class Bid
{
public Member Member { get; set; }
public DateTime DatePlaced { get; set; }
public decimal BidAmount { get; set; }
}
Member and Item are aggregate roots here and Bid is contained within Item.
Now let's say that I have application use case: "Get all bids posted by specific member". Does that mean that I would have to first get all Items (eg. from data base via repository interface) and then enumerate all bids for each Item trying to find matching Member? Isn't that a bit inefficient? So a better way would be then to aggregate Bid objects inside of Member. But in that case consider the new use case: "Get all bids for specific item". Now again we need to go other way around to get all bids...
So taking into account that I need to implement both of these use cases in my application, what is the right and efficient way to model this domain then?
Your domain should really reflect only Command (CQRS) requirements (update/change data). I presume that you need Queries (read data, no update/change of data): "Get all bids for specific item" and "Get all bids posted by specific member". So, this "querying" has nothing to do with the domain, as the query implementation is independent on the command implementation (command is calling a domain method). This gives you a freedom to implement each query in an efficient way. My approach is to implement an efficient DB view getting you only data you want to display in UI. Then you create a new class called BidForItemDto (DTO = data transfer object) and you map data from DB view into a collection of BidForItemDto (you can do it manually via ADO.NET or use NHibernate (preferred, does everything for you)). The same for the second query, create a new class called BidPostedByMemberDto.
So, if it is queries you need, just forget about domain, realize that it's just data you want to display in UI, and query them efficiently from the DB. Only when you do some action in UI (click a button to place a bid for instance), it's executing a command "place a bid", which would at the end call domain method Item.PlaceBid(Member member, DateTime date, decimal amount). And btw, IMHO is it an Item which "has many bids", and the domain method "place bid" would surely need to access previous bids to implement the whole logic correctly. Placing bids collection into Member does not make much sense to me...
From the top of my head some examples of DB views and sql queries:
Get all bids for specific item:
create view BidForItemDto
as
select
i.ItemId,
b.BidId,
b.MemberId,
b.DatePlaced,
b.BidAmount
from Item i
join Bid b ON b.ItemId = i.ItemId
query:
SELECT *
from BidFormItemDto
where ItemId = <provide item id>
Get all bids posted by specific member:
create view BidPostedByMemberDto
as
select
m.MemberId,
b.BidId,
b.MemberId,
b.DatePlaced,
b.BidAmount
from Member m
join Bid b ON b.MemberId = i.MemberId
query:
SELECT *
from BidPostedByMemberDto
where MemberId = <provide member id>
I have an aggregate that includes the entities A, AbstractElement, X, Y and Z. The root entity is A that also has a list of AbstractElement. Entities X,Y and Z inherit from AbstractElement. I need the possibility to add instances of X, Y and Z to an instance of A. One approach is to use one method for each type, i.e. addX, addY and addZ. These methods would take as arguments the values required to create instances of X, Y and Z. But, each time I add a new type that inherits from AbstractElement, I need to modify the entity A, so I think it's not the best solution.
Another approach is to use an abstract add method addAbstractElement for adding AbstractElement instances. But, in this case, the method would take as argument an instance of AbstractElement. Because this method would be called by entities located outside of the aggregate, following DDD rules/recommandations, are these external entities authorized to create instances of AbstractElement? I read in the Eric Evans book that external entities are not authorized to hold references of entities of an aggregate other than the root?
What is the best practice for this kind of problem?
Thanks
From Evan's book, page 139:
"if you needed to add elements inside a preexisting AGGREGATE, you might create a FACTORY METHOD on the root of the AGGREGATE"
Meaning, you should create a factory method on the root (A) which will get the AbstractElement's details. This method will create the AbstractElement (X/Y/Z) according to some decision parameter and will add it to its internal collection of AbstractElements. In the end this method return the id of the new element.
Best Regards,
Itzik Saban
A few comments. As the previous answerer said, it's a good practice to use a factory method. If you can avoid it, never create objects out of the blue. Usually, it's a pretty big smell and a missed chance to make more sense out of your domain.
I wrote a small example to illustrate this. Video is in this case the aggregate root. Inside the boundaries of the aggregate are the video object and its associated comments. Comments can be anonymous or can have been written by a known user (to simplify the example, I represented the user by a username but obviously, in a real application, you would have something like a UserId).
Here is the code:
public class Video {
private List<Comment> comments;
void addComment(final Comment.Builder builder) {
this.comments.add(builder.forVideo(this).build());
// ...
}
}
abstract public class Comment {
private String username;
private Video video;
public static public class Builder {
public Builder anonymous() {
this.username = null;
return this;
}
public Builder fromUser(final String username) {
this.username = username;
return this;
}
public Builder withMessage(final String message) {
this.message = message;
return this;
}
public Builder forVideo(final Video video) {
this.video = video;
return this;
}
public Comment build() {
if (username == null) {
return new AnonymousComment(message);
} else {
return new UserComment(username, message);
}
}
}
}
public class AnonymousComment extends Comment {
// ...
}
static public class UserComment extends Comment {
// ...
}
One thing to ponder on also is that aggregate boundaries contain objects and not classes. As such, it's highly possible that certain classes (mostly value objects but it can be the case of entities also) be represented in many aggregates.
I'm trying to avoid ending up with an anaemic Domain Model, so I'm attempting to keep as much logic as possible within the domain model itself. I have a method called AddIngredient, which needs to add a new KeyedObject to my Recipe Aggregate.
As the Domain Models themselves are meant to be devoid of repositories, I'm getting the ingredient via a business rule class:
public class Recipe : AggregateObject
{
public void AddIngredient(int ingId, double quantity)
{
GetIngredientMessage message = new GetIngredientMessage();
message.IngredientId = ingId;
GetIngredient handler = ServiceLocator.Factory.Resolve<GetIngredient>();
Ingredient ingredient = handler.Execute(message);
Ingredients.Add(new OriginalIngredient()
{
Ingredient = ingredient,
Quantity = quantity
});
}
}
As you can see, I'm using a line the line ServiceLocator.Factory.Resolve<GetIngredient>(); to obtain my GetIngredient business rule class. GetIngredient is a simple command handler that looks like the following:
public class GetIngredient : ICommandHandler<Ingredient, GetIngredientMessage>
{
private readonly IIngredientRepository _ingredientRepository;
public GetIngredient(IIngredientRepository ingredientRepository)
{
_ingredientRepository = ingredientRepository;
}
}
I assign my IoC factory class to the ServiceLocator.Factory, so the Domain has the ability to use its own interfaces, without seeing the concrete class implementation:
ServiceLocator.Factory = new IoCFactory();
I'm pretty sure I'm doing something wrong as it all feels a little bit bodge-like.
Can anyone spot anything blatantly wrong?
Is there a more appropriate way to instantiate a business rule handler such as GetIngredient without a static reference to my IoC Factory?
I suggest you introduce another layer into the design -- the Application layer. This layer responsibility would be to translate commands (either explicitly encapsulated in command objects or passed implicitly as int ingId, double quantity) into domain model invocations (Recipe.AddIngredient).
By doing so you'll move the responsibility of finding an ingredient by its id to a layer above domain, where you can safely make use of repositories directly without introducing unwanted coupling. The transformed solution would look something like this:
public class ApplicationLayer
{
private readonly IRecipeRepository _recipeRepository;
private readonly IIngredientRepository _ingredientRepository;
/*
* This would be called by IoC container when resolving Application layer class.
* Repositories would be injected by interfacy so there would be no coupling to
* concrete classes.
*/
public ApplicationLayer(IRecipeRepository recipeRepository, IIngredientRepository ingredientRepository)
{
_recipeRepository = recipeRepository;
_ingredientRepository = ingredientRepository;
}
public void AddIngredient(int recipeId, int ingId, double quantity)
{
var recipe = _recipeRepository.FindById(recipeId);
var ingredient = _ingredientRepository.FindById(ingId);
recipe.AddIngredient(ingredient, quantity);
}
}
And the now simplified Recipe class would look something like this:
public class Recipe : AggregateObject
{
public void AddIngredient(Ingredient ingredient, double quantity)
{
Ingredients.Add(new OriginalIngredient()
{
Ingredient = ingredient,
Quantity = quantity
});
}
}
Hope that helps.