I'm new to thymeleaf, and have a little problem causing headache.
I have an entity "Payment", and Payment has "Manager" entity as attribute.
#ManyToOne
#JoinColumn(name = "manager")
private Manager manager;
And Manager Entity has attributes like id, name, .. so on.
I want to access to the 'name' attribute from Payment Dto, like below.
<td><span th:text="${payment.manager.id}"></span></td>
However, it generates error code.
org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
I tried <td><span th:text="${payment.manager}"></span></td> this, and the program was running without error, although nothing was shown in that line.
How can I access to inner attribute(ex. name) of a nested objects like
Payment { Manager { id, name, ... } }
this?
First try to run the API on postman and check whether the data is coming right means
payment :{
id: "",
.
.
"manager":{
"name":"",
.
.
.
}
}
If not then there is problem while saving the entity payment. You saved the payment correctly but may be you didn't set the entity manager in the payment entity using ManyToOne relationship. Like this
payment.setManager(manager);
Maybe you did an error in saving that.
Related
I have defined two Spring boot REST resources
POST /customer
The above resource is for adding a customer with the below JSON as a request
{
"customerFirstName" : "John"
"customerLastName" : "Doe"
"customerAddress" : {
"addressLine1" : "22 XYZ Drive"
"addressLine1" : "22 suite"
"state" : "PY"
"country" : "Ind"
"zipCode" : "1235312"
}
}
Now I need to implement update the customer info, so the below resource is defined. The requirement is any information related to customers can be updated. So the Input JSON in case of an update is the same as in the case of add request. The only caveat the information that is not provided will not be updated. Only information that is provided will be updated.
PUT /customer/{customerId}
Question : I want to use Spring boot Bean request validation. However, the validation requirements are different for adding and updating resources, so not able to use the same Customer domain model. However, the domain model in both cases is exactly the same so this is causing a code duplication. How can I avoid that or is it correct to move the validation outside and code.
Example : In the case of adding a customer it is mandatory to provide a customer address, so one can use annotation like #NotNull. However, in the case of updating the customer, the customer address is not mandatory.
You should be able to use validation groups and keep a single model class. Each constraint has groups attribute that you can use to define a validation scheme. You can have a Create group that you'll use only in the POST request and ignore in the PATCH one:
interface Create {}
class Customer {
#NotNull(groups = Create.class)
private String firstName;
#NotNull(groups = Create.class)
private String lastName;
//....
}
And then as you are using Spring you'd want to take a look at #Validated annotation. This one allows you to define the particular groups you want to validate against:
#PostMapping("/customer")
public ResponseEntity<Customer> create(#RequestBody #Validated(Create.class) Customer customer) {
// do your thing
}
You can also check this part of the documentation to learn more about groups and their capabilities
I have the following entities:
Area
Listing
They are both many-to-many:
An area can have many listings
A listing can have many areas
Both Area and Listing have other fields like name, domain, etc.
I'm using Spring Web RestController as a way to update the entities.
For example:
#PutMapping("/{id}")
public Area update(#PathVariable Long id, #RequestBody Area update) {
return areaRepository.save(update);
}
However, as an Area can have many thousands of Listings, it's not practical to pass them all in the update request when I just want to update the Area name and other basic fields in my web application.
For example, the update json in the http request would be:
{
"id" : 69,
"name" : "San Francisco",
"domain" : "foo",
...
}
When serialised, the area instance above will have a listings field equal to null (obviously) and then when saved, all association are remove from this Area.
I'm thinking that I could do a select-then-update set of operations and only update the values necessary but that is cumbersome - especially when there are many dozens of non-association fields.
The question would be: how can I try to keep to the above code and http request and not remove all of the existing Listing associations when saving the input area? Is this possible? I want to update the name and other basic fields but not the association fields.
You can use the BeanUtilBean(org.apache.commons.beanutils.BeanUtilsBean).
Step 1: Create custom beanutilbean class.
#Component
public class CustomBeanUtilsBean extends BeanUtilsBean {
#Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value==null)return;
super.copyProperty(dest, name, value);
}
}
Step 2: In your controller while updating. first get the Area from database & use copyProperties method as shown in below.
#PutMapping("/{id}")
public Area update(#PathVariable Long id, #RequestBody Area update) {
Area areaDB = areaRepository.findOne(update.getId());
customBeanUtilsBean.copyProperties(areaDB,update);//it will set not null field values of update to areaDB.
return areaRepository.save(areaDB);
}
Hope this will helps you..:)
Since you are using spring-data-jpa repository you can write a new method that takes the changed values of Area object with #Modifying and #Query annotations on it.
In the #Query you specify the HQL query with update statement as in here
I am using rest services with spring data . when i get data from single table its return proper result in json format . but when i use many to many association between entities using hibernate i am getting an un acceptable result with following error in chrome's console .
Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING
My result looks like there just one row repeating itself , and its a particularly that field which is being used in new generated table by association.
[{"id":7,"name":"Milk pack","description":"haleeb","imageUrl":"milk.jpg","price":350.00,"category":null,"orderDetail":[]},{"id":8,"name":"oil","description":"olive oil ","imageUrl":"/resources/uploads/olive.png","price":670.00,"category":null,"orderDetail":[{"id":263,"productlist":[{"id":10,"name":"Mobile","description":"awesome design, slim design ","imageUrl":"/static/uploads","price":34569.00,"category":null,"orderDetail":[{"id":263,"productlist":[{"id":10,"name":"Mobile","description":"awesome design, slim design ","imageUrl":"/static/uploads","price":34569.00,"category":null,"orderDetail":[{"id":263,"productlist":[{"id":10,"name":"Mobile","description":"awesome design, slim design ","imageUrl":"/static/uploads","price":34569.00,"category":null,"orderDetail":[{"id":263,"productlist":[{"id":10,"name":"Mobile","description":"awesome design, slim design
.
.
.and so on
My entities are following
Product table
#ManyToMany(mappedBy = "productlist")
private List<OrderDetail> orderDetail =new ArrayList<OrderDetail>();
OrderDetail table
#ManyToMany
#JoinTable(
name="order_detail_productlist",
joinColumns=#JoinColumn(name="order_detail_id", referencedColumnName="id"),
inverseJoinColumns=#JoinColumn(name="productlist_id", referencedColumnName="id"))
private Set<Product> productlist = new HashSet<Product>();
I am using spring data jpa repository to get them
List<Product> findAll();
Note: which products those are not ordered yet that are working properly
You need the all log for the information, it maybe cause by loop when with jackson. So you need add #JsonIgnoreProperties.Please see http://stackoverflow.com/questions/3325387
My Problem is solved by using jackson 2.0 documentation
by Adding following annotation or OrderDetail table
#JsonBackReference
it breaks loop and show result properly
I've managed to correctly set up a Laravel DataTable with the following code in a controller method.
// Retrieve (potentially filtered) data
$users = User::with("role", "language", "country")->select([
"support_code", "first_name", "last_name", "subscription_expires",
"email_address", "user_name", "location",
"role_id", "language_id", "country_id"
]);
// Return data as JSON
return Datatables::of($users)->make(true);
However, I now wish to move this code out of the controller and into a domain object/separate class. The problem is that this doesn't work as the DataTables JS sends a long query string via its Ajax method, and this isn't being passed along to the domain class.
I have two questions. First, how do I send this query string to the domain class? Second, how do I offer it up to the Datatables::of($users) -> make(true) method?
Lol. My fault. I forgot to include use Yajra\Datatables\Datatables;
Because it was an Ajax request, I didn't get the namespace error message.
I have a form changeed the properties of my object CUSTOMER. Each customer has related ORDERS. The ORDER's table has a column customer_id which is used for the mapping. All works so far, I can read customers without any problem.
When I now e.g. change the name of the CUSTOMER in the form (which does NOT show the orders), after saving the name is updated, but all relations in the ORDERS table are set to NULL (the customer_id for the items is set to NULL.
How can I keep the relationship working?
THX
UPDATE: Mapping Info
The Orders are mapped on the Customer side
#OneToMany
#JoinColumn(name = "customer_id")
#OrderBy("orderDate")
private Collection<Order> orders = new LinkedList<Order>();
UPDATE
Seems like adding a
#SessionAttributes("customer")
to my model, changing the method to
public String saveTrip(#ModelAttribute("customer") Customer customer, BindingResult result, SessionStatus status) {
if (!result.hasErrors()) {
this.tripManager.saveTrip(trip);
}
else {
logger.debug("Form data included errors, did not save data");
BindingUtils.logBindingErrors(result, logger);
}
status.setComplete();
return "redirect:/customers/";
}
Could solve the issu. But is this a good way of solving it???
One way would be not to submit the CUSTOMER Object from the form.
Instead submit the customer, submit only the customers ID and the new Name. In the controller you have to load the Customer by the submitted ID and then update the Name. And persist the Customer again.
HI,
Make cascade="none" attribute of many-to-one relationship from order side.
Thanks.