Getting file with model field in spring mvc - spring-mvc

I am try to upaload a file with some other fields for model, but I can't binding file with those fields.
handling request.
#RequestMapping(value="/products", method=RequestMethod.POST)
public String saveProduct(#Valid #ModelAttribute("product") Product product, BindingResult result){
if (result.hasErrors()) {
return "manageProduct";
}
}
in model class with some other fields
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String code;
#NotBlank(message = "Product name can't be blank")
private String name;
#NotBlank(message = "Brand name can't be blank")
private String brand;
#NotBlank(message = "Description can't be blank.")
#Size(min = 10, max = 500, message = "Description shoud be contain 10 and 500 characters")
#JsonIgnore
private String description;
#Min(value = 1)
#Column(name = "unit_price")
private float unitPrice;
private int quantity;
#JsonIgnore
#Column(name = "is_active")
#OrderBy("id ASC")
private boolean active;
#Column(name = "category_id")
#JsonIgnore
private int categoryId;
#Column(name = "supplier_id")
#JsonIgnore
private int supplierId;
private int purchases = 0;
private int views = 0;
#Transient
private MultipartFile file;
//getters and setters
}
form also enctype="multipart/form-data" and method is "post".
When try to upload file with others fields, then errors occurs.
And I am using spring boot.

Assuming you are using Spring Data and JPA then Spring Content provides a solution to uploading and associating content with your entity.
As you are using Spring Boot it is easy to add. Add the following dependencies:
pom.xml
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-jpa-boot-starter</artifactId>
<version>0.0.11</version> <!-- Or 0.1.0 for Spring Boot 2 -->
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>0.0.11</version> <!-- Or 0.1.0 for Spring Boot 2 -->
</dependency>
Add the following attributes to your Product entity so that content can be associated with it (this is in place of your Multipart file field):
Product.java
#Entity
public class Product {
...existing fields...
#ContentId
private String contentId;
#ContentLength
private long contentLength = 0L;
#MimeType
private String mimeType;
// no need for MultipartFile
Create a ContentStore (the equivalent of a JpaRepository for BLOBs):
ProductContentStore.java
#StoreRestResource(path="productsContent")
public interface ProductContentStore extends ContentStore<Product, String> {
}
When you run your application Spring Content will see the ProductContentStore interface and the spring-content-jpa dependency and inject an JPA implementation of this interface for you meaning that you don't have to write this yourself. It will also see the spring-content-rest dependency and add an #Controller implementation that forwards GET, PUT, POST and DELETE REST requests onto the ProductContentStore bean meaning that you don't have to write this controller either. REST endpoints will be available at /productsContent so...
after creating your product and getting an ID, you can then:
curl -X POST -F "image=#/some/local/path/product.jpg" /productsContent/{productId}
to upload product.jpg and associate it with your product entity. And:
curl /productsContent/{productId} will fetch it again.
Yes, this does imply that you need TWO requests to create a product and associate an image with it. If you have valid reasons that justify why this needs to be one request and not two then raise an issue against Spring Content github repo and we can look into adding support this for you.
HTH

Related

how do i create roles and use those roles in JSPS?

how do I create user defined roles and then how do I use them to code my JSPS to present them according to the user role type in a spring MVC web application
If I understand you correctly.
Use jstl.
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
With the " if " condition, you can create different menu calls for different users.
JSTL - Core Tag
<c:if test="${example != null}">
<center>
${example}
</center>
</c:if>
Below are the steps to do that.
1.Create a role entity.
2.Create a user entity.
3.Establish relationship between both tables like (OneToMany or #ManyToMany based on your requirement)
4.Insert a role in table.
5.create a user by assigning the role to the user.
6.Once DB relationships are done then inside JSP page you can get role and put a condition to check that and you are done.
Code for step 1 :
#Entity
public class Role implements GrantedAuthority {
private static final long serialVersionUID = 1L;
#NotNull
private String roleName;
private String description;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
//getters and setters and other fields like roleName,description etc.
}
Step 2 &3:
#Entity
public class User extends BaseEntity implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(unique = true)
private String userId;
#ManyToOne
private Role role;
//getters and setters and other fields like password,etc.
}
Step 6 :
<sec:authorize ifAnyGranted="ROLE_ADMIN" >
write code here which only ADMIN can see
</sec:authorize>

Nested entity in request body is ignored

The domain model is
An industry has many companies
A company belongs to an industry
So I have my entity classes:
#Entity
public class Industry {
#Id #GeneratedValue
private Long id;
private String name;
#OneToMany(targetEntity = Company.class, fetch = FetchType.LAZY, mappedBy = "industry")
private Collection<Company> companies = new ArrayList<>(0);
// Getters and setters
}
and
#Entity
public class Company {
#Id #GeneratedValue
private Long id;
private String name;
#ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER, optional = false)
private Industry industry;
// Getters and setters
}
My controller:
#RestController
#RequestMapping("/companies")
public class CompaniesController extends ControllerBase {
#RequestMapping(method = RequestMethod.POST)
public Company create(#RequestBody Company company) {
company.getIndustry(); // returns null
// ...
}
}
When I send request POST /companies with request body
{
"name": "Walmart",
"industry": {
"id": 1
}
}
I found that company.getIndustry() always returns null. How can I make the controller accept nested entities?
Entities are session based. They usually work on basis of Lazy loading I.e only the first level is loaded and other attributes are loaded on Demand. You cannot pass it from one layer to other. (service to controller)
The correct way to do it. Have a Value object (a simple class) n the controller. Use it between front end and back end. Send the same value object to service. And use the entity only between Service and DAo layer
public class CompanyVO{
private Long id;
private String name;
private IndustryVO industryVO; // create similar class
// Getters and setters
}
#RestController
#RequestMapping("/companies")
public class CompaniesController extends ControllerBase {
#RequestMapping(method = RequestMethod.POST)
public Company create(#RequestBody CompanyVO companyVO) {
companyVO.getIndustry(); // returns null
// ...
}
}
This may be because you need another Spring message converter instead of the default one. Just add jackson to your pom.xml and Spring will use MappingJackson2HttpMessageConverter.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>

Usage of ReflectionUtils and BeanUtils for private fields

I need to set some private fields in an object using another object's fields. Those two objects may not be instances of same class.
What I see from a short reading, I can use Apache's BeanUtils and Spring's ReflectionUtils for that. I couldn't find a satisfying explanation for them regarding security, performance, support etc.
The solution will be used in production environment too, so I need a concrete solution.
Which approach do you suggest for such a task.
I think you need use just the BeanUtils library. See my sample, i do a copy properties from CustomerBean to SellerBean.
package testes.beanutils;
import org.apache.commons.beanutils.BeanUtils;
public class Main {
public static void main(String[] args) throws Exception {
Customer customer = new Customer();
customer.setId((long)1);
customer.setName("Bruno");
customer.setLastname("Tafarelo");
Seller seller = new Seller();
BeanUtils.copyProperties(seller, customer);
System.out.println(customer);
System.out.println(seller);
}
}
class Customer {
private Long id;
private String name;
private String lastname;
//getters and setters
//toString
}
class Seller {
private Long id;
private String name;
private int sales;
//getters and setters
//toString
}

Why Jackson Annotation Is Being Ignored For Class Inside List?

I'm using Jackson in Spring MVC #ResponseBody to generate JSON for jqGrid. I'm using a POJO like this for JSON required by jqGrid:
public class Grid<T> implements Serializable {
private int totalPages;
private int currentPage;
private long totalRecords;
private List<T> listData;
// getter & setter...
}
I'm putting domain model retrieved from Hibernate JPA (maybe a proxy because there is lazy fetching in some attributes) such as:
#Entity #Cacheable
public class Item implements Serializable {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Version
private int version;
#NotBlank
private String name;
#JsonIgnore #Lob #Basic(fetch=FetchType.LAZY)
private byte[] image;
// getter and setter...
}
This is my code in Spring MVC controller:
#RequestMapping(value="listgrid", method=RequestMethod.GET, produces="application/json")
#ResponseBody
public Grid<T> listGrid(#RequestParam(value="page", required=false) Integer page,
#RequestParam(value="rows", required=false) Integer rows,
#RequestParam(value="sidx", required=false) String sidx,
#RequestParam(value="sord", required=false) String sord,
#RequestParam(value="_search", required=false) String search) {
// ...
Grid<T> grid = new Grid<T>();
Page<T> objPage = retrieveData(...);
grid.setListData(objPage.getContent());
grid.setCurrentPage(objPage.getNumber()+1);
grid.setTOtalPages(objPage.getTotalPages());
grid.setTotalRecords(objPage.getTotalElements());
return grid;
}
I've put #JsonIgnore in image attribute, but the resulting JSON will always contains image. How to ignore this attribute?
Have you tried #JsonIgnore on the getter ?

ASMX Web Service (ASP.net 2.0) - Serializable Dictionary not serialized

All,
I have an instance of ProjectBudget class returned from a web method.
Ex:
[WebMethod()]
public ProjectBudget LoadBudget(int id)
{
ProjectBudget budget = BudgetManager.LoadBudget(id);
return budget;
}
The ProjectBudget class contains the following defintion:
public class ProjectBudget
{
public int Id = -1;
public long VersionNumber = -1;
public string QuoteNumber = "";
public string CurrencyCode = "";
public ProjectInfo Project;
public ClientInfo Client;
public readonly List<InventoryItem> Inventory = new List<InventoryItem>();
public readonly List<Staff> Staff = new List<Staff>();
public readonly List<CodeType> Departments = new List<CodeType>();
public readonly SerializableDictionary<string, string> Tasks = new SerializableDictionary<string, string>();
public ProjectBudget()
{
}
}
All public fields you see are serialized just fine with the exception of Tasks field, which is completely ignored by XML serializer. Since we all know by now that Dictionaries cannot be handled by XML serializer, I use a serializable dictionary (which is just a dictionary that implements IXmlSerializable) here but XML serializer decides to ignore it completely, i.e. the XML output does not contain any tasks and the generated proxy class doesn't have this field.
I need to figure out how to tell the XML serializer not to omit this field.
Btw, what is interesting is that a web method that returns SerializableDictionary works fine!
A very similar question as yours appears to have been asked already: Link.
Use DataContractSerializer or try explicitly implementing your getter (and setter), as per this link.

Resources