Need to see the search result of the:
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
public User findByUsername(String username);
}
which I call from my controller:
#RequestMapping(value = "/users/find", method = RequestMethod.GET)
public #ResponseBody User findByUsername(#RequestParam("username") String userName) {
return usersRepo.findByUsername(userName);
}
The method above is called via:
#GET("/users/find")
public User findByUsername(String userName);
And the class User is here:
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String username;
etc...
Results of the default methods I can see in my browser by typing e.g. localhost:8080/users
I tried many possible requests but it seems that I'm missing something. Any help is appreciated.
Try this:
Here you will get plane User object on browser so try to change return type to String.
#RequestMapping(value = "/users/find", method = RequestMethod.GET)
#ResponseBody
public User findByUsername(#RequestParam("username") String username) {
return usersRepo.findByUsername(username);
}
Hit this URL from local machine
localhost:8080/users/find?username=99
Now I recognize that my question was about testing an API. The best solution for it is to use Postman. The tool is really easy to learn and request results are in a better form.
Related
I am using spring boot with postgresql to save row in table and print table rows. My problem is that all the WebController methods are being executed twice but only when I open the url in chrome. If I do this in internet explorer, it works fine. How can I stop this in chrome?
I am putting the code of four files for the reference although I don't think anything's wrong in the code. Do I need to change browser settings or something?
User.java
#Entity
#Table(name="users")
public class User implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="name")
private String name;
#Column(name="email")
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
#Override
public String toString() {
return String.format("User[id=%d, name='%s', email='%s']",this.id,this.name,this.email);
}
}
UserRepository.java
public interface UserRepository extends JpaRepository<User, Long>{
}
WebController.java
#RestController
public class WebController {
#Autowired
private UserRepository repository;
#GetMapping("home")
public String home() {
System.out.println("whaaat");
return "hi";
}
#GetMapping("/save")
public String process() {
repository.save(new User("vidhi","vd#gmail.com"));
System.out.print("apple ");
return "Done";
}
#RequestMapping("findall")
public String findAll() {
String result = "";
for(User u: repository.findAll()) {
result += u.toString() + "<br>";
}
return result;
}
}
application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=postgres
spring.datasource.password=
spring.jpa.generate-ddl=true
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
I got to know that the methods are running twice because of double addition of rows in the table and "whaaat" is printed twice in console but only when in chrome.
Any help would be wonderful.
Thanks for your time.
First. Try "Network" tab in Chrome Developer Tools (try F12 button) to identify how many requests are actually sent.
Second.
It's generally not a good idea to save any data at "GET" request, because of it's semantic, browser doesn't expect changes on server side and can invoke request multiple times (can't produce a use case for that, but it's totally not forbiden for browser to do that) or get it from cache.
Hi everyone in my project I have 2 classes a Login Class and a Sports Class. And I want to pull a specific field from the database in the Sports Class based on the user login.
So for example if my login is 12345 the database should pull the respective sport name based on my login.
How do I connect the 2 classes in such a way so that the database can pull data based on my login in the previous class?
You can have a singleton class and store user details in that class when login happened and later you can access that from any other class.
public class UserDetails{
private static UserDetails instance = new UserDetails();
private UserDetails(){}
private String userId;
public static UserDetails getInctance(){
return instance;
}
public String getUserId(){
return userId;
}
public void setUserId(String userId){
this.userId = userId;
}
}
Then in Login class,
UserDetails.getInctance().setUserId("12345");
In Sports Class,
String userId = UserDetails.getInctance().getUserId();
Then user userId in query.
I am assuming time of calling you have the user information.Then simply you can get the userid and pass as method argument to sports detail method.Try to make classes loosely coupled.
Consider following UserDTO class and UserController exposing endpoints to create, update and get User.
Having the id property in the UserDTO class does not make sense for create and update. If I use swagger or another auto generated API documentation then it shows that the id can be passed in create end point. But the system does not use it as ids are generated internally.
If I look at get then probably I can get rid of the id property but it is certainly required in a list user end point.
I was thinking of returning internal User domain object in get/list end points. This way I can then get rid of id property form UserDTO class.
Is there any better option I can employ for this?
public class UserDTO {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#RestController
#RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Void> create(#RequestBody UserDTO user) {
}
#RequestMapping(value = "{id}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<UserDTO> get(#PathVariable("id") int id) {
}
#RequestMapping(value = "{id}", method = RequestMethod.PUT)
#ResponseBody
public ResponseEntity<Void> update(#PathVariable("id") int id, #RequestBody UserDTO user) {
}
}
This question may have been asked but I could not find. So excuse me for duplicate question.
Data Transfer Object (DTO) is a pattern that was created with a very well defined purpose: transfer data to remote interfaces, just like web services. This pattern fits very well in REST APIs and DTOs will give you more flexibility in the long run.
I would recommend using tailored classes for your endpoints, once REST resource representations don't need to have the same attributes as the persistence objects.
To avoid boilerplate code, you can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.
For details on the benefits of using DTOs in REST APIs, check the following answers:
Why you should use DTOs in your REST API
Using tailored classes of request and response
To give your DTOs better names, check the following answer:
Giving meaningful names to your DTOs
What's about creating two different interfaces :
interface UserDTO {
public String getName ();
public void setName (String name);
}
interface IdentifiableUserDTO extends UserDTO {
public Long getId ();
public void setId (Long id);
}
class DefaultUserDTO implements IdentifiableUserDTO {
}
and then use the Interface in your controller instead of the DTO class :
#RestController
#RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<Void> create(#RequestBody IdentifiableUserDTO user) {
}
#RequestMapping(value = "{id}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<UserDTO> get(#PathVariable("id") int id) {
}
#RequestMapping(value = "{id}", method = RequestMethod.PUT)
#ResponseBody
public ResponseEntity<Void> update(#PathVariable("id") int id, #RequestBody UserDTO user) {
}
}
I am using Spring web services REST API that gives the JSON response.
The API usage:
#ResponseBody
#RequestMapping(value="/user", method = {RequestMethod.POST})
Details user(#RequestParam("username")
String username, #RequestParam("password") String password)
The JSON coming is:
{
"result":{
"details" : {
"firstName":"My",
"lastName":"God",
"enabled": false,
"id":927878192,
"language":"en_US",
}
}
}
I am having a Details class with the getter and setter methods for firstName, lastName, enabled, id and language.
The class is annotated with #JsonIgnoreProperties(ignoreUnknown = true).
However I don't want to show language and enabled in JSON response.
So in my java code, I did the following for language:
details.setLanguage(null);
That worked fine.
But I can't do details.setEnabled(null) because the enabled variable is primitive that can take true or false but not null. So my JSON response always has "enabled": false.
What can be done so that this field will not be a part of JSON response.
Try to use #JsonIgnore annotation on field level.
For example:
#JsonIgnore
private boolean isActive;
If you want to ignore the property only for selected response I suggest using #JsonView from com.fasterxml.jackson.annotation package but it could be an overkill.
First you need to create a class with an interface inside:
public class View {
public interface UserDetailed {}
}
After that you specify in your class which field should be visible only for specific 'profile':
public class User {
// Other fields
#JsonView(View.UserDetailed.class)
private List<Role> roleCollection = new ArrayList<Role>();
// Other fields, getters and setters
}
Then on the controller's method that needs to display that property you do:
#Controller
public class UserController{
#RequestMapping(value = "/userWithRoles", method = RequestMethod.GET)
#JsonView(View.UserDetailed.class)
public User getUserWithRoles() {…}
#RequestMapping(value = "/userWithoutRoles", method = RequestMethod.GET)
public User getUserWithoutRoles() {…}
}
The result is: only the controller methods that have the same #JsonView as the field will display it. Other will ignore it. It allows you to manage the visibility of the fields depending on the use case.
Here you can read more about it:
http://wiki.fasterxml.com/JacksonJsonViews
Put #JsonIgnore on the enabled getter method.
If you want to ignore it only during serialization but you need it when deserializing (if you need to edit that field from some method of the REST API), you can annotate with #JsonSetter("enabled") the enabled setter method.
Example:
public class Details {
....
private boolean enabled;
...
#JsonIgnore
public boolean isEnabled()
#JsonSetter
public void setEnabled(boolean enabled)
}
If you for some API method need enabled and for others no, the cleanest way to do so is to have two DTOs:
public class DetailsBasic {
private String firstName;
private String lastName;
private long id;
// getters and setters
}
public class Details extends DetailsBasic {
private boolean enabled;
private boolean language;
// getters and setters
}
And then in your controller:
#ResponseBody
#RequestMapping(value="/user", method = {RequestMethod.POST})
DetailsBasic user(#RequestParam("username")
String username, #RequestParam("password") String password) {
return ...
}
#ResponseBody
#RequestMapping(value="/otherMethod", method = {RequestMethod.POST})
Details otherMethod(#RequestParam("username")
String username, #RequestParam("password") String password) {
return ...
}
I am using spring 4 REST.
I have a base class and many other class extends the same.
For example, Employee is the base class and other classes hr, engineer, trainer etc etc extends the employee.
I have to create REST API to create the different type of employee.
The interface is one POST which accepts all the type of employees. I cannot create different interface for each sub type. From the base, I know what is the sub type.
#RequestMapping(value= "/test/{employeeType}", method = RequestMethod.POST)
public void createEmp(#RequestBody Employee employee){
//If type is HR, I want to cast to HR type
//Is there any way we can take generic object in spring rest and then manage internally ?
}
Maybe try this?
#RequestMapping(value= "/test/{employeeType}", method = RequestMethod.POST)
public void createEmp(#PathVariable String employeeType, #RequestBody EmployeeDTO employeeDTO){
transform(employeeType,employeeDTO);
}
Here EmployeeDTO will contain all possible parameters so it can construct any of the child classes then based on the employeeType you just transform into domain object(Employee)?
Edit2 as requested
Here is sample code:
public class Employee {
private String name;
}
public class Hr extends Employee {
private String department;
}
public class Hr extends Employee {
private String department;
}
Then the DTO class should look like this:
public class EmployeeDTO {
private String name;
private String course;
private String department;
}
Then when you know your type you transform to whatever your want with all the necessary values in the DTO
Edit: Now when I think about it this also may be an option but I will need to see your classes.
#RequestMapping(value= "/test/employee", method = RequestMethod.POST)
public void createEmp(#RequestBody Employee employee){
#RequestMapping(value= "/test/hr", method = RequestMethod.POST)
public void createHr(#RequestBody Hr hr){