Send Data from Angular to Springboot over POST - java

I am trying to send one json from my frontend angular project to the backend which is springboot.
It is the first time I am using these 2 technologies so I lack in experience.
I am not quite sure if my http post method in Angular is wrong or if my backend isn't listening to the data which are supposed to come.
I will attach both code parts so that you can help me. Thank you in advance!
Here is a picture of the chrome console:
Http Errorcode 404
http error image
Backend:
#RestController
#RequestMapping
#CrossOrigin(origins = "http://localhost:4200")
public class RequestController {
private RolesRequestRepository rolesRequestRepository;
#PostMapping("/sendrolesrequest")
void addRequest(#RequestBody RolesRequest rolesRequest) {
rolesRequestRepository.save(rolesRequest);
}
#GetMapping("/sendrolesrequest")
public List<RolesRequest> getRequests() {
return (List<RolesRequest>) rolesRequestRepository.findAll();
}
}
#Entity
public class RolesRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String requester = "";
private String recipient = "";
public RolesRequest(String recipient, String requester) {
this.recipient = recipient;
this.requester = requester;
}
public RolesRequest(){
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getRequester() {
return requester;
}
public void setRequester(String requester) {
this.requester = requester;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
}
Here is the angular frontend part:
#Injectable()
export class RequestService {
sendRolesRequestUrl = 'sendrolesrequest'; // URL to web api
private handleError: HandleError;
constructor(
private http: HttpClient,
httpErrorHandler: HttpErrorHandler) {
this.handleError = httpErrorHandler.createHandleError('RequestService');
}
sendRolesRequest (rolesRequest: RequestModel): Observable<RequestModel> {
//console.log("addRolesRequest try post:" + rolesRequest.print());
return this.http.post<RequestModel>(this.sendRolesRequestUrl, rolesRequest, httpOptions)
.pipe(
catchError(this.handleError('sendRolesRequest', rolesRequest))
);
}
testPost() {
const headers = new Headers();
headers.append('Content-Type', 'application/json; charset=utf-8');
this.http.post(this.sendRolesRequestUrl, {'key1': 'value1', 'key2': 'value2'}, httpOptions)
.subscribe(() => {}, err => console.error(err));
}
}
export class RequestFormulaComponent implements OnInit {
onSendRequest() {
this.requestService
.sendRolesRequest(this.rolesRequest)
.subscribe();
}
}
I would be very happy if someone helps me out here. I am struggling on this topic over a week.
Is that even the way how a backend application should communicate with the webpage? If not, how can I do it otherwise?

You're using JPA entity as DTO, and have no setters/getters, also there is no default constuctor, modify your RolesRequest like this:
#Entity
public class RolesRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String requester = "";
private String recipient = "";
public RolesRequest() { }
public RolesRequest(String recipient, String requester) {
this.recipient = recipient;
this.requester = requester;
}
public String getRequester() { return this.requester; }
public void setRequester(String r) { this.requester = r;}
public String getRecipient() { return this.recipient; }
public void setRecipient(String r) { this.recipient = r;}

Are your backend and angular app running on the same port? (backend and frontend are combined in the same application)
You are calling http://localhost:4200/sendrolesrequest and I think that's a request on the Angular app itself. You get a HTTP 404 error code (NOT FOUND)
You should call the endpoint of the backend application. It's running on port 8080 for example so call http://localhost:8080/sendrolesrequest (or with other port if backend is running on another port)
Change:
sendRolesRequestUrl = 'sendrolesrequest';
to:
sendRolesRequestUrl = 'http://localhost:8080/sendrolesrequest';

Related

Required, request body is missing: public when I try loading Swagger

I am trying to access the swagger URL from my Spring-Boot application using the post request. But getting a 400-Bad request and it says the request body is missing. But the same request works fine in Postman.
Controller:
#RestController
public class IdVController {
#Autowired
private IdService idService;
#Autowired
protected FileUtility util;
/** The Constant STATUS. */
private static final String STATUS = "status";
/** The Constant SUCCESS. */
private static final String SUCCESS = "success";
/** The Constant SYSTEM. */
private static final String SYSTEM = "SYSTEM";
#RequestMapping(value ="/idApi")
public ResponseEntity<MarketPlaceResponse>
validateIdData(#RequestBody VerifyIdDTO verifyIdDTO) throws Exception {
JSONObject rawResponse = idService.validateId(verifyIdDTO);
IdVerifyEntity DTOResponse = (IdVerifyEntity)util.convertToEntity(rawResponse.toString(), IdVerifyEntity.class);
if (rawResponse.get(STATUS).equals(SUCCESS)) {
DTOResponse.setCreated_by(SYSTEM);
DTOResponse.setCreated_date(new
java.sql.Date(System.currentTimeMillis()).toString());
}
//return ResponseBuilder.buildResponse(DTOResponse);
MarketPlaceResponse response = new MarketPlaceResponse();
response.setResponse(DTOResponse);
return new ResponseEntity<MarketPlaceResponse>(response,HttpStatus.OK);
}
}
Request DTO:
public class VerifyIdDTO {
#NotBlank(message="Owner ID should not be empty")
private String id;
private String citizenship;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCitizenship() {
return citizenship;
}
public void setCitizenship(String citizenship) {
this.citizenship = citizenship;
}
}
I am contacting an external service by building URL and using GET from this POST method
this is the swagger URL
localhost:8080/idvalidationservice/swagger-ui.html
You can see the error message in this screenshot.

WebSocket build configuration for STOMP/SpringBoot

I try to create endpoints /api/streams/positions and /api/streams/orders but confused with configuration.
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/api/streams");
config.setApplicationDestinationPrefixes("streams");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/api/streams/positions", "/api/streams/orders")
.setAllowedOrigins("*")
.withSockJS();
}
}
#Controller("/api/streams")
public class WebSocketController {
private final SimpMessagingTemplate simpMessagingTemplate;
#MessageMapping("/positions")
public void positionsSendToBrowserAuthenticatedClient(PositionDto position) {
this.simpMessagingTemplate.convertAndSendToUser(user.getUsername(),"/streams/position", position);
}
}
What is the configuration I need for the controller work? And what is enableSimpleBroker() and setApplicationDestinationPrefixes() actually means? Can I have one endpoint to get and send messages at the same time?
UPDATE_1 +DTO
#Data
#NoArgsConstructor
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class PositionDto {
#JsonProperty("id")
private Long id;
#JsonProperty("type")
private PositionType type;
#JsonProperty("openAt")
private Timestamp openAt;
#JsonProperty("openPrice")
private BigDecimal openPrice;
#JsonProperty("orders")
private List<OrderDto> orders;
}
public enum PositionType {
LONG("LONG"), SHORT("SHORT");
public final String value;
PositionType(String value) {
this.value = value;
}
public String getType() {
return value;
}
}
Maybe I could help because it seems that you're building a kind of trading application, but need more informations: are you building a websocket yourself or do you want to get data from an existing one to build a DTO?
The SendTo is like an transmitter. You just have to "subscribe" to this ws like this, for an angular application's service (for example):
getTestnetCurrentPrice(symbol: string): Observable<any> {
const subject = webSocket(`wss://YOURWEBSOCKETADRESS?param=${param}`);
return this.http.get(`https://YOURWEBSOCKETADRESS?param=${param}`);
}
You can also test your websocket with a simple const like that:
const yourSocket = new WebSocket('wss://YOURWEBSOCKETADRESS' + this.param());
You can find a lot of good tutorials with cryptocurrencies plateform who will help you.
Here is an example of a front Angular financial service example dedicated to a websocket:
#Injectable({
providedIn: 'root'
})
export class CandlecollectService {
private baseUrl = 'http://YOURBACKENDPOINT/';
obj: any;
object: JSON;
constructor(private http: HttpClient) { }
extractCandles(symbol: string, interval: string, limit: number): Observable<any> {
return this.http.get(`${this.baseUrl}${symbol}/${interval}/param`);
}
getCurrentPrice(symbol: string): Observable<any> {
const subject = webSocket(`wss://YOURWEBSOCKETURL?symbol=${symbol}`);
return this.http.get(`https://YOURWEBSOCKERURL?symbol=${symbol}`);
}
}

Spring Boot server error while POST with Retrofit2, only happens when there are relationships in the database

I POST some data with Retrofit2 to a Spring Boot REST service and there are a lot of exceptions occurring in the server. This happens when I have relations in my database.
I have a REST service over a Spring Boot application that runs over the Heroku services, I was doing a login and a register tasks with an Android application, I am using Retrofit2 in Android to POST the data to the REST service, everything was working well until for some other reasons I create a relationship between users in my database, this relationship is a "follow", this is, create a relationship in a follow table where I have the ID of the user that is following and an ID of the user that is followed. When I create this relationship into the database and I try to login with the method that I created, I got a bunch of errors into the REST service that I do not know why is this happening.
So in Android I have the call of my Retrofit2 client and a method that creates the service passing as a parameter the UserService.class with the HTTP methods. I also pass as a parameter the user of the class User where have the information that I want to POST, then I call the enqueue method.
RetrofitClient.createService(UserService.class).login(user).enqueue(new CallBack<User>(){
#Override
public void onResponse(Call<User> call, Response<User> response) {
//Some logic here
}
});
Into my UserService.java I have the method that POST the user object information.
public interface UserService {
#POST("login")
public Call<User> login(#Body User user);
}
Now in the backend side I have a REST controller where I have the login endpoint that will be consumed for Retrofit2.
#PostMapping(path = "login", consumes = "application/json", produces = "application/json")
#CrossOrigin(origins = "*", methods= {RequestMethod.GET,RequestMethod.POST})
public Object login(#RequestBody String json) {
//Some logic here
}
As I said this endpoint runs fine when there are no relationships over a user into the DB, but when a user follow another one, this is, when there is a new row into the follow table, lets say:
follow table:
id_follow id_user_follower id_user_following
1 1 2
At the example above the user 1 follows the user 2, and when I try to login, this is, use the login method in the UserService class it throws me a bunch of errors.
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
And this repeat over 300 lines of errors.
The thing here is that between the bunch of error the server return a 200 HTTP response, I managed the exceptions in Spring Boot and I catch that, when I catch I send a code for an error to my Android Retrofit2 client, but the login does not work.
Expected result:
After sending the POST from Retrofit2 to Spring Boot the response have to be a HTTP 200 response but no exceptions have to happen into the server.
Actual result:
There is a 200 HTTP response from the server but there are a lot of exceptions into the server that return an error code to the Android application and the login does not work.
This is the entity that I want to return as JSON from the RestController in Spring Boot.
#Entity
#Table(name = "users")
public class User extends AuditModel{
private static final long serialVersionUID = 1700575815607801150L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idUser;
private String name;
private String lastName;
#Column(name = "nick_name", unique = true)
private String nickName;
private String avatarResource;
#Column(unique=true)
private String email;
private String password;
private String birthDate;
private String gender;
private String postalCode;
private int active;
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getAvatarResource() {
return avatarResource;
}
public void setAvatarResource(String avatarResource) {
this.avatarResource = avatarResource;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Long getId() {
return idUser;
}
public void setId(Long idUser) {
this.idUser = idUser;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
/* Relations */
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Comment> comments;
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<UserMemory> userMemories;
public List<UserMemory> getUserMemories() {
return userMemories;
}
public void setUserMemories(List<UserMemory> userMemories) {
this.userMemories = userMemories;
}
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Vote> votes;
public List<Vote> getVotes() {
return votes;
}
public void setVotes(List<Vote> votes) {
this.votes = votes;
}
#OneToMany(mappedBy = "userFollower", fetch = FetchType.LAZY)
private List<Follow> usersFollowers;
public List<Follow> getUsersFollowers() {
return usersFollowers;
}
public void setUsersFollowers(List<Follow> usersFollowers) {
this.usersFollowers = usersFollowers;
}
#OneToMany(mappedBy = "userFollowing", fetch = FetchType.LAZY)
private List<Follow> usersFollowing;
public List<Follow> getUsersFollowing() {
return usersFollowing;
}
public void setUsersFollowing(List<Follow> usersFollowing) {
this.usersFollowing = usersFollowing;
}
}
By having fetchtype.LAZY, some of the values won't exist during serialization. This will make the ObjectMapper to try to fetch these and it all will end up in some kind of infinite loop.
It is never recommended to serialize #Entity annotated classes because database tables can change and that in turn will change the API for the calling clients.
Best way is to have specific ResponseDTOs that you transfer your data to before serialization so that the API and the database tables can change without breaking anything.
So, the problem was that in the backend I was using the writeValueAsString of the ObjectMapper class like this.
public Object register(#RequestBody String json){
User user = new User();
user.set...
...
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(user);
}
For some reason the writeValueAsString method gives a StackOverFlowException for a recursive behavior when there is a relationship into the database, this is a problem related with JPA or Hibernate, I am not sure about which one of those.
The solution was to write my own method to build a JSONObject with the information of my POJO:
public String buildUserJSON(User user) {
JSONObject userJson = new JSONObject();
userJson.put("idUser", user.getIdUser());
...
return userJson.toString();
}
And then call this method in my RestController to build the JSON that I want to return. As I said I do not know what was the problem but at least this was the solution for me.
Note: I found the solution to this be cause in the past I was with a problem similar like this one but when I was trying to return a List<T> as a JSON, so, I though that was related with the same thing.
Regards.
The problem was with Jackson, so to get out of this problem you most use two annotations in the relations of your entities.
More information, please see the next link: Here is the answer
Hope it can help for anyone.

Android Java Spring JSON response has $ in key. How to parse?

I'm new to Java. I'm using Spring to consume a REST api that outputs JSON. With the tutorials on the Spring website I can easily have the JSON response converted to an object of my desired class. The problem is now that one of the keys in the JSON response is $id. I cannot make a variable with a dollar sign in it. I assume I should define some configuration somewhere that such a name would be converted into something acceptable. I don't know how.
My Rest request code:
protected LoginResult doInBackground(Void... params) {
try {
Log.i(TAG, "Making Login request");
//TODO: Make this a setting
final String url = "https://someurl.com/api/login";
LoginCredentials login = new LoginCredentials("foo#bar.com", "qwerty123");
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
LoginResult result = restTemplate.postForObject(url, login, LoginResult.class);
Log.d(TAG, "Got the LoginResult.");
return result;
} catch (Exception e) {
//TODO: Exception handling
Log.e(TAG, e.getMessage(), e);
}
return null;
}
The resulting JSON looks something like this:
{
"_id":{
"$id":"98765432"
},
"name":"Person Guy",
"email":"foo#bar.com",
"roles":[
"user"
],
"active":true,
"created":{
"sec":1439117849,
"usec":856000
},
"session":{
"token":"12345678",
"user_id":"98765432",
"created":{
"sec":1439134272,
"usec":0
},
"last_extended":{
"sec":1439134272,
"usec":0
},
"expires":{
"sec":1439998272,
"usec":0
}
}
}
The $id part is where things get difficult. The LoginResult class looks like this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class LoginResult {
private String name;
private String email;
private MongoId _id;
/* Getters and setters */
}
The MongoId class looks like this (The JsonIgnoreProperties is now added to avoid exceptions):
#JsonIgnoreProperties(ignoreUnknown = true)
public class MongoId {
private String id; //This is $id in the JSON response.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Any help would be largely appreciated.
You can use the #JsonProperty("$id") annotation in MongoId to tell how the JSON is mapped to your Java object:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MongoId {
#JsonProperty("$id")
private String id; //This is $id in the JSON response.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Here is a quick overview for reference.

Retrofit Android Application GET JSON from Node.js Server

I solved the problem.
I was sending plain-text in the server.
Changed the line to read:
response.writeHead(200, {'Content-Type': 'application/json'});
Quick question. My friend recommended looking into Retrofit rather than using my ASync task for my REST android application. I am having one small problem since I am new to the system. The server runs using Node.js to send JSON objects by means of .stringify() and so when I retrieve an object it is a String rather than a JSON, and I cannot convert it to my List of the appropriate objects. I am guessing the error is due to a cast exception because it is sending a string because I get the exception:
com.google.gson.JsonSyntaxException
Any help would be great. Here is the code I thought would be appropriate.
Android Client Code Example below:
private void requestData() {
RestAdapter adapter = new RestAdapter.Builder().setEndpoint(ENDPOINT).build();
UnitAPI unit_api = adapter.create(UnitAPI.class);
unit_api.getUnits(new Callback<List<Unit>>() {
#Override
public void success(List<Unit> t, Response response) {
units = t;
updateDisplay();
}
#Override
public void failure(RetrofitError error) {
Log.d("Failure UnitGet()", error.getMessage());
}
});
}
Android Unit.class:
public class Unit {
private String ID;
private long bearing;
private long lat;
private long lng;
private String type;
public String getID() {
return ID;
}
public void setID(String ID){
this.ID = ID;
}
public long getBearing() {
return bearing;
}
public void setBearing(long bearing){
this.bearing = bearing;
}
public void setLat(long lat){
this.lat = lat;
}
public long getLat(){
return lat;
}
public void setLng(long lng){
this.lng = lng;
}
public long getLng(){
return lng;
}
public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}
}
The server sends the .json file via the command:
if (method == "GET") {
response.write(JSON.stringify(unitsJSON));
}
Any thoughts on how I can convert it to a list of units from the string on the client side or a json object on the server side?
Thanks!
I solved the problem. I was sending plain-text in the server. Changed the line to read:
response.writeHead(200, {'Content-Type': 'application/json'});
I think you must add json-parser to package using npm
then
in response write
res.end(JSON.stringfy('your resp0onse here'));

Categories