I want to create DTO class for User. my input to program is
firstname, lastname,lastname.role,group1,group2,group3.
so for each user role consist of group_1,group_2,group_3.....
In database i want to store in following format
demo,demo,demo,roleId, gorup_1_name group_1_Id
demo,demo,demo,roleId, gorup_2 and group_2_Id
demo,demo,demo,roleId, gorup_3 and group_3_Id
I was able separate all this things , but i want to assign this value to userDTO class and stored into database. basically im new to core java part. so how can create structure for this?
A Data Transfer Object (DTO) class is a java-bean like artifact that holds the data that you want to share between layer in your SW architecture.
For your usecase, it should look more or less like this:
public class UserDTO {
String firstName;
String lastName;
List<String> groups;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<String> getGroups() {
return groups;
}
public void setGroups(List<String> groups) {
this.groups = groups;
}
// Depending on your needs, you could opt for finer-grained access to the group list
}
One thing to add:
The essence of a DTO is that it transfers data across the wire. So it will need to be Serializable.
http://martinfowler.com/eaaCatalog/dataTransferObject.html
Related
So I am wondering what the best way to process an edit request based on a user role.
Say I have the following PostMapping:
#PostMapping(value = "/edit")
public ResponseEntity<String> editIoc(#RequestBody GeneralPojoAllFields editRequest)
the GeneralPojoAllFields looks like this:
public class GeneralPojoAllFields {
private String firstName;
private String lastName;
private String onlyAdminCanEditField;
}
This is the pojo the the admin will be able to use and that will eventually get mapped into the entity class to be saved to the database. However, if we have a regular user who wants to edit it and hypothetically they aren't restricted in the UI would that design work? What I am currently thinking is I would have a user pojo like so:
public class UserPojo {
private String firstName;
private String lastName;
}
After the request mapping comes we check if the user is either regular user or an admin. If it is a regular user we just map the GeneralPojoAllFields to the UserPojo and it wont map over the onlyAdminCanEditField and continue from there.
Is there a better way to do this?
First, your backend should be as independent of the UI as possible. So, access control in UI is a good to have design, but you should not depend upon it.
Now, coming back to your question, yes you can use SecurityContextHolder to find out if the user if regular user/admin. However, if its possible, I would suggest making two controllers, one for admin and one for regular user. Use #PreAuthorize on the admin controller to restrict access. Having two separate controllers will increase readability of your code tremendously.
Additionally, you can call the same service class method from both the controllers. And since you already have two POJO classes, you can use them in #RequestBody and let Spring take care of the mappings for you.
Well, it depends what you think a better way would be. It also depends a bit on your data source. But as there is no information on that here, I would suggest that a better way to do yours is by inheritance.
Make UserPojo the super class and GeneralPojoAllFields extend that class.
UserPojo.java:
public class UserPojo {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public UserPojo() {}
public UserPojo(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
GeneralPojoAllFields.java:
public class GeneralPojoAllFields extends UserPojo {
private String onlyAdminCanEditField;
public String getOnlyAdminCanEditField() {
return onlyAdminCanEditField;
}
public void setOnlyAdminCanEditField(String onlyAdminCanEditField) {
this.onlyAdminCanEditField = onlyAdminCanEditField;
}
public GeneralPojoAllFields() {}
public GeneralPojoAllFields(String firstName, String lastName, String onlyAdminCanEditField) {
super(firstName, lastName);
this.onlyAdminCanEditField = onlyAdminCanEditField;
}
}
App.java:
public class App {
public static void main(String[] args) {
UserPojo up1 = new UserPojo();
up1.setFirstName("MyFirstName");
up1.setLastName("MyLastName");
GeneralPojoAllFields gpaf1 = new GeneralPojoAllFields();
gpaf1.setFirstName("MyFirstName");
gpaf1.setLastName("MyLastName");
gpaf1.setOnlyAdminCanEditField("yes");
}
}
I am following this spring guide:
https://spring.io/guides/gs/accessing-mongodb-data-rest/
Everything is perfect, however if I want to POST a document with manual id, I am not able to do that.
Here is what all I have done:
I inserted one document from Mongo shell by the command db.person.insert({"_id": "111111", "firstName" : "Vikas", "lastName" : "Prasad"});
This works fine and if I do a GET at http://localhost:8080/people from Postman, I can see the person document with id 111111 in the response having self href as http://localhost:8080/people/111111
But if I am sending a POST request from Postman at http://localhost:8080/people with body as {"_id": "222222", "firstName" : "Aadish", "lastName" : "Patodi"}, the document is getting inserted with an auto id instead of 222222. Because of which obviously I cant access this docuemnt by doing a GET at http://localhost:8080/people/222222 unlike the case when I used insert() from the shell to insert a document with manual id. Instead I have to hit a GET at http://localhost:8080/people/57bc29ada3fab115cc9b546b to fetch this second document.
Just to check if I am POSTing the {"_id": "222222", "firstName" : "Aadish", "lastName" : "Patodi"} again, its getting inserted again at a new auto generated id: http://localhost:8080/people/57bc2bdaa3fab115cc9b546c. It means MongoDB is not even looking at the _id, else it must have thrown duplicate key error.
I tried searching various sources. All I can found is an implementation of the data access code separately in JAVA at back end and calling respective MongoDB methods.
My question is:
Just like in the given tutorial they are performing every operation without defining any JAVA back end code for data access from MongoDB for auto id documents, is there a way to do the same for manual id documents?
Or just for this one use case I have to implement the data access code at the back end?
I am using CorsFilter to handle cross origin requests.
Edit:
Below is the Person class:
package hello;
import org.springframework.data.annotation.Id;
public class Person {
#Id private String id;
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
I have tried:
-> adding getter and setter for id attribute
-> renaming id to employeeNumber
-> renaming id to employeeNumber and adding getter and setter for employeeNumber
None of the above three solved the issue.
as discussed on the comment, looks like your _id field is not mapped correctly. Can you check if the _id is mapped correctly in the pojo ?
Finally, I got it working by renaming id with _id and adding getter and setter for the same in the Person class.
package hello;
import org.springframework.data.annotation.Id;
public class Person {
#Id private String _id;
private String firstName;
private String lastName;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
I'm using Spring to implement a RESTful web service. One of the endpoints takes in a JSON string as request body and I wish to map it to a POJO. However, it seems right now that the passed-in JSON string is not property mapped to the POJO.
here's the #RestController interface
#RequestMapping(value="/send", headers="Accept=application/json", method=RequestMethod.POST)
public void sendEmails(#RequestBody CustomerInfo customerInfo);
the data model
public class CustomerInfo {
private String firstname;
private String lastname;
public CustomerInfo() {
this.firstname = "first";
this.lastname = "last";
}
public CustomerInfo(String firstname, String lastname)
{
this.firstname = firstname;
this.lastname = lastname;
}
public String getFirstname(){
return firstname;
}
public void setFirstname(String firstname){
this.firstname = firstname;
}
public String getLastname(){
return lastname;
}
public void getLastname(String lastname){
this.lastname = lastname;
}
}
And finally my POST request:
{"CustomerInfo":{"firstname":"xyz","lastname":"XYZ"}}
with Content-Type specified to be application/json
However, when I print out the object value, the default value("first" and "last") got printed out instead of the value I passed in("xyz" and "XYZ")
Does anyone know why I am not getting the result I expected?
FIX
So it turned out that, the value of request body is not passed in because I need to have the #RequestBody annotation not only in my interface, but in the actual method implementation. Once I have that, the problem is solved.
So it turned out that, the value of request body is not passed in because I need to have the #RequestBody annotation not only in my interface, but in the actual method implementation. Once I have that, the problem is solved.
You can do it in many ways, Here i am going to do it in below different ways-
NOTE: request data shuld be {"customerInfo":{"firstname":"xyz","lastname":"XYZ"}}
1st way We can bind above data to the map as below
#RequestMapping(value = "/send", headers = "Accept=application/json", method = RequestMethod.POST)
public void sendEmails(#RequestBody HashMap<String, HashMap<String, String>> requestData) {
HashMap<String, String> customerInfo = requestData.get("customerInfo");
String firstname = customerInfo.get("firstname");
String lastname = customerInfo.get("lastname");
//TODO now do whatever you want to do.
}
2nd way we can bind it directly to pojo
step 1 create dto class UserInfo.java
public class UserInfo {
private CustomerInfo customerInfo1;
public CustomerInfo getCustomerInfo1() {
return customerInfo1;
}
public void setCustomerInfo1(CustomerInfo customerInfo1) {
this.customerInfo1 = customerInfo1;
}
}
step 1. create another dto classCustomerInfo.java
class CustomerInfo {
private String firstname;
private String lastname;
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
}
step 3 bind request body data to pojo
#RequestMapping(value = "/send", headers = "Accept=application/json", method = RequestMethod.POST)
public void sendEmails(#RequestBody UserInfo userInfo) {
//TODO now do whatever want to do with dto object
}
I hope it will be help you out. Thanks
The formatting on this is terrible, but this should work for jackson configuration.
<!-- Use Jackson for JSON conversion (POJO to JSON outbound). -->
<bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<!-- Use JSON conversion for messages -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>
ALso, as mentioned in a comment, your JSON is wrong for your object.
{"firstname":"xyz","lastname":"XYZ"}
does appear to be the correct JSON for your object.
Sample Data :
[
{
"targetObj":{
"userId":1,
"userName":"Devendra"
}
},
{
"targetObj":{
"userId":2,
"userName":"Ibrahim"
}
},
{
"targetObj":{
"userId":3,
"userName":"Suraj"
}
}
]
For above data this pring controller method working for me:
#RequestMapping(value="/saveWorkflowUser", method = RequestMethod.POST)
public void saveWorkflowUser (#RequestBody List<HashMap<String ,HashMap<String ,
String>>> userList ) {
System.out.println(" in saveWorkflowUser : "+userList);
//TODO now do whatever you want to do.
}
remove those two statements from default constructor and try
I created a simple project with GAE and i put in my package 'model' the PMF.java (Persistence Manager Factory Class) and a class (Employee.java) that i can show you here:
#PersistenceCapable
public class Employee {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String firstName;
#Persistent
private String lastName;
#Persistent
private Date hireDate;
public Employee(String firstName, String lastName, Date hireDate) {
this.firstName = firstName;
this.lastName = lastName;
this.hireDate = hireDate;
}
// Accessors for the fields. JDO doesn't use these, but your application does.
public Key getKey() {
return key;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
}
When i click on Google->Generate Cloud Enpoint Client Library, i receive the following error message:
Error in Generating API: this project does not have cloud endpoint classes. What does it mean? Thank you so much
You have done the first part i.e. created your model.
When you try to generate the Cloud Endpoint Client Library, the tool is look for Java classes that are annotated with the #API annotation, so that it knows which classes are your endpoints.
What you should try is the following series of steps :
Create a new Project and add your model i.e. Employee
Generate the Endpoint classes for Employee by simply right clicking on the class in the Project and selecting Google -> Generate Cloud Endpoint class. This will generate the Endpoint class EmployeeEndpoint along with PMF. java.
Now, right-click on the project and select Google -> Generate Cloud Endpoint Client Library and you should be good since the tool will find the Endpoint class (EmployeeEndpoint) that has been annotated correctly.
I am a novice in Java World. How to avoid confusion over variable declaration in MVC pattern over same variable?
For Example,
In Servlet (Controller):
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
In Bean (Model):
private String firstname;
private String lastname;
public Person(String FirstName, String LastName) {
setFirstName(FirstName);
setLastName(LastName);
}
//Getter and Setter Methods
public String getFirstName() {
return firstname;
}
public void setFirstName(String FirstName) {
this.firstname = FirstName;
}
public String getLastName() {
return lastname;
}
public void setLastName(String LastName) {
this.lastname = LastName;
}
In DAO (Data Access Layer):
public void savePerson(String firstName, String lastName) {
// Method statements
}
And in JSP (View):
${person.firstname} ${person.lastname}
My Questions/Confusion?
What is the proper way of declaring same variable in different
modules(controller,models,views,dao)? And how should I avoid confusion?
Is there any conventions I have to follow while declaring variables in different
modules?
Should variables in Servlets and DAO be same? Should variables in Models/Bean
be different from Servlet and DAO?
In your servlet these would be method variables. That's pretty fine.
In your Model this works as a Model's properties. That's pretty fine, too.
In view you are actually referring to Model's properties, and not declaring any variable, whatsoever.
In DAO, you are actually, persisting your Model.
So, In Servlet/Controller this will be something more like this,
Person p = new Person();
p.setFirstName(request.getParameter("firstname"));
p.setLastName(request.getParameter("lastname"));
And in your DAO, it would be more like this,
public void savePerson(Person person) {
// Method statements
}
Hence, declaration only happens in Model. I hope it clears your confusion.
I think the variable names you have used are fine. You can name your classes based on the type of the module. So you could name your classes using names like MyApplicationController, EmployeeModel, EmployeeDAO, etc.