OpenEntityManagerInView is not working with JSF - spring

I have created sample project using JSF+Spring+JPA.
I have 2 entities Customer and Order where customer can have more than one order so mapping between Customer and Order is #OneToMany.
Customer Class is as below
#Entity
#NamedQueries
(
{
#NamedQuery(name=Contact.QUERY_FIND_ALL, query="FROM Contact"),
}
)
public class Customer
{
public final static String QUERY_FIND_ALL="findAll";
#OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private List<Order> orders;
public List<Order> getOrders()
{
return orders;
}
public void setOrders(List<Order> orders)
{
this.orders = orders;
}
}
My View works like below
1st Case:
We load all cutomer and display them on screen with and arrow in
front of each record this happens in one request.
now when end-user click on arrow we want to display all order of
that Customer.
but i am getting Lazy load exception even though i am using OpenEntityManagerInView.
2nd Case:
If I load both Customer and Order in one request it work fine.
is there somthing like that if we load parent in one request we cant load its lazy association in second request?
why its not working in 1st case and working in second case?
and
more important what is the other solution to archive it?

When you load customer on your data access layer class (e.g CustomerDAO) you have to get at least one of each child property to bypass lazy proxy, maybe it would look like this
public class CustomerDAO{
public Customer getCustomer(String custId){
Customer cust = //your method to retrieve customer
List<Order> orders = cust.getOrders();
for(Order ord:orders){
ord.getOrderName(); // you have to get at least one of each child property to bypass lazy proxy
}
}
}
Hope it would help

Related

Mapping of Dynamic fields in RestfulController POST (save) method

How do I enable RestfulController to auto-map or even manually map the dynamic fields to domain classes implementing MongoEntity? I have a domain class as below:
class Company implements MongoEntity<Company> {
String id = UUID.randomUUID().toString()
String name
String email
String phone
}
And I have a RestfulController setup for CRUD operations as below
class CompanyController extends RestfulController<Company> {
#Transactional
def save(Company company) {
if(company.hasErrors()) {
respond company.errors
}
else {
company.insert(flush:true)
respond company, status: CREATED
}
}
}
When I POST a request with some additional JSON fields, how do I get them auto-mapped to gorm_dynamic_attributes ? Currently the company object does not return any information on the dynamic attributes. Another problem I am facing is that request.JSON is also null so I cannot manually map either. Any suggestions would be highly appreciated.
I'm pretty sure, that the problem is not in data binding of your controller, but rather in persisting of the domain class instance.
I would change the domain class like so:
import grails.gorm.annotation.Entity
#Entity
class Company {
String id
String name
String email
String phone
def beforeValidate() {
if( !id ) setId UUID.randomUUID().toString()
}
static mapping = {
id generator:'assigned'
}
}
to use the assigned generator. You could put your id generation either in the controller / service code, or leave it inside the domain class' beforeValidate. In the later case pay special attention to when the id shall be generated, as beforeValidate() is called pretty often. Also note, that inside beforeValidate() a setter must be called.
I tested the similar domain class of mine with save() and insert() and in both cases that works like charm.

Spring cacheable annotation with multiple key

I have 2 ways to lookup a customer record (code below), customerGuid and customerId are 2 different fields in Customer object.
Suppose that i lookup customer by customerId once, is there a way for me to lookup customer by guid directly from cache without querying backend, Assuming both the methods return type is Customer.
public class CustomerLookup {
#Cacheable("customerCache")
public Customer getCustomerByGuid(final String customerGuid) {
// some implementation here...
}
#Cacheable("customerCache")
public Customer getCustomerByCustId(final String customerId) {
// some implementation here...
}
}
You can add a 2nd parameter to one method which will only serve as cache key. Example use customerId as key and proceed like this:
#Service
public class CustomerLookup {
#Autowired
#Lazy
private CustomerLookup self;
#CachePut("customerCache", key="#customerId")
public Customer getCustomerByGuid(final String customerGuid, String customerId) {
Customer customer = self.getCustomerByCustId(final String customerId);
//......
}
}
Note the self-injection of CustomerLookup if you don't do that the cache won't work when you call the getCustomerByCustId(final String customerId) method in getCustomerByGuid. Also note the #CachePut instead of #Cacheable on getCustomerByGuid, with this you are sure that this method will be called everytime.

Update multiple fields of JPA Entity

I have JPA entity Customer having say 50 fields and I would like to update it from the end user using html form.
I am passing one instance of entity to html page form (using thymeleaf), this form is having only 20 fields out of 50 (including ID field). Now once the form is submitted, I would like to update 20 fields from data received using form to the database. I am not getting solution for above issue. One solution is to update individual field but I don't think it is good solution.
#Entity
public class Customer
{
...
50 fields
}
My get method:
#GetMapping(value = "customer")
public String customer(Model model) {
Customer customer = null;
Optional<Customer> optional = customer Repo.findById(customerId);
if (optional.isPresent()) {
customer = optional.get();
}
model.addAttribute("customer", Customer);
return "customer";
}
Html form:
<form action="updateCustomer">
----20 fields which I would like to get update from user are here
</form>
#PostMapping(value = "updateCustomer")
public String updateCustomer(Model model, #ModelAttribute Customer customer) {
if(customer==null) {
System.out.println("Customer object is null");
}
else
{
customerRepo.save(customer);
}
return "savedCustomer";
}
In the post method when I get customer object it is having only 20 fields data not 50(Customer entity is having total fields) because html form is having only 20 fields for update. How to update the old customer object having 50 fields using the new customer object having updated 20 fields.?
There are three ways in the past that I solved this problem
1) have the page GET the Customer object in question, use the object to pre-populate the form, and then POST the changed customer object. The benefit is that the user changing the Customer sees all info related to the Customer, and you have a easy merge on the backend. The drawback is an additional REST call.
2) Create a DTO, and transfer non-null fields from the DTO to the entity. The benefit is you don't have to update all the fields in the form, and no extra network call. the drawback is that it's a pure pain in the rear end.
3) Create a DTO, and make it an entity to save. The benefit is that it's a easy merge back to the database, nothing prevents you from mapping the same table and fields to multiple entities. The drawback is that you have to worry about concurrency issues, which may just not work in your workflow, and the DTO is basically specific per form.
To make partial updates to entity, you either need to use Criteria API or JPQL query ... this is called projection in JPA, here is a quick example ,
Note : You might not be able to use this feature if you are using an old version of JPA query parser (no JPQL updates) + old version of JPA (when no CriteriaUpdate lib was there) you will then need to fetch the object from DB with the id passed from the client, update the 20 properties from the client and save the changes back
Below solution worked for me:
Helper Class:
public class BeanCopy {
private static final Set<Class<?>> primitiveTypes = new HashSet<Class<?>>(
Arrays.asList(Boolean.class, Character.class, Byte.class, Short.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class, String.class, Date.class));
public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException
{
new BeanUtilsBean() {
#Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value != null && (primitiveTypes.contains(value.getClass()) )) {
super.copyProperty(dest, name, value);
}
}
}.copyProperties(dest, source);
}
}
This is how I copied and forced changes to database:
try {
BeanCopy.nullAwareBeanCopy(DBcustomer,customer);
customerRepo.save(DBcustomer);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Please let me know any better solution is available for the above problem.

From request object to the database

I have an app with an AngularJS front-end and a Spring MVC back-end. I'm having some trouble with converting/mapping request objects to domain/dto objects.
On one page you can add a new order to the system, the POST payload would look something like this:
{
memo: "This is some extra info for order",
orderLines: [{productId:3, quantity:4}, {productId:2, quantity:5}, {productId:1, quantity:4}],
shippingDate: "2014-10-08T19:16:19.947Z",
warehouseId: 2
}
The Spring MVC controller method looks like this:
#RequestMapping(value = "/order", method = RequestMethod.POST)
public ResponseEntity<Void> addOrder(#RequestBody #Valid OrderRequest orderRequest, UriComponentsBuilder b) throws Exception {
// the magic
}
Where OrderRequest is filled with the values of the POST request, the OrderRequest and OrderLineRequest look like this:
public class OrderRequest {
private Long id;
private Date shippingDate;
private String memo;
private List<OrderLineRequest> orderLines;
private Long warehouseId;
public OrderRequest() {
}
// getters and setters ommitted
}
public class OrderLineRequest {
private Long id;
private String productCode;
private int quantity;
public OrderLineRequest() {
}
}
My question now is, in order to save an Order object with orderService.add(order) I need to construct the Order object based on the values that were sent in the request. Where/how do I do this?
OPTION 1
The OrderRequest class could have a makeOrder() method with just returns an Order object like so:
public Order makeOrder() {
Order order = new Order();
order.setMemo(this.memo);
order.setShippingDate(this.shippingDate);
...
}
Then I'd have to map the OrderLineRequest which could have their own makeOrderLine method:
public OrderLine makeOrderLine() {
OrderLine orderLine = new OrderLine();
orderLine.setQuantity = this.quantity;
...what to do with only the productId?
}
As you can see I can set the quantity but in the request I only received the productId, but in the database I save the productCode, productName as well, so I need that info from the database, but I don't want to make a database call from the Request object...I also don't want to half of the mapping in the request object and the rest of the mapping in the controller where I do have access to the services.
OPTION 2
I can use Dozer to do the mapping for me, but that would mean injecting the services into the Dozer custom converters which seem equally unclean to me...
OPTION 3
I pass the OrderRequest object to the service layer and let the service layer handle it, but my question would remain, how exactly would the service layer convert it, say you have the method addOrder like this:
public void addOrder(OrderRequest orderRequest) {
}
Would you call another service to convert from one to the other as I don't really want this conversion in a business logic method?
Any help would be appreciated
use the #RequestBody to map your jsonObject that is send with the request , to a DTO .
please refer to the following tutorial .
hope that helps .
and please ask if there is something not clear .

ASP.NET MVC Pattern - How to use two seperate repositores in a controller(using DI)

I have two very simple tables. Product and ProductCategory (ProductCategory is like a 'lookup' table for Product). On my controller, for my Index() method I want to list the categories of the products. When the user clicks on a category, I want to pass my category to my List() method to show all the products of a specific category.
I'm using ninject DI framework; I currently have something like this.
private IProductCategory productCategoryRepository;
private IProduct productRepository;
public StoreController(IProductCategory productCategoryRepository)
{
this.productCategoryRepository = productCategoryRepository;
}
public ViewResult Index()
{
return View(productCategoryRepository.GetCategories());
}
public ViewResult List(string category, int page = 1) //Use default value
{
...
};
I have basic repositories per table/entity (i.e. GetCategories(), GetProducts(), GetProductsByCategory..etc.) What's the best way...or how can I use two seperate repositories in a controller? I'd prefer not to pass them both through a controller.
Note: Product and ProductCategory is not considered an aggregate.
As i mentioned earlier, a service layer would help you resolve this. The service layer is a point of contract between the user interface and the middle tier. This could be a WCF service or a simple service implementation i am showing below.
public interface IMyProductService
{
IList<Product> GetProducts();
IList<Product> GetProductsByCategory();
IList<Category> GetCategories();
}
public class MyProductService : IMyProductService
{
IProductRepository _prodRepo;
IProductCategoryRepository _catRepo;
public MyProductService(IProductRepository prodRepo, IProductCategoryRepository catRepo)
{
_prodRepo = prodRepo;
_catRepo = catRepo;
}
// The rest of IMyProductService Implementation
}
Your MVC controller will have a reference to IMyProductService likely using constructor injection with a DI framework of your choice.

Resources