I'm using Angular 4 with Spring backend. And.... My post request working fine. But the get request don't work. Look the code:
Frontend Service:
import { Injectable } from '#angular/core';
import 'rxjs/add/operator/toPromise';
import { Aluno } from '../models/aluno.model';
import {HttpClient} from "#angular/common/http";
import {Observable} from "rxjs/Observable";
#Injectable()
export class UserDataService {
private url = 'http://localhost:8080/getAluno';
constructor(private http: HttpClient){}
getAluno():Observable<Aluno>{
return this.http.get<Aluno>(this.url);
}
}
My spring backend provider:
import com.google.gson.Gson;
import com.ifmg.tcc.TADs.Aluno;
import com.ifmg.tcc.TADs.LoginObject;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
#CrossOrigin(origins = "http://localhost:4200")
#RestController
public class LoginProvider {
Gson gson = new Gson();
private boolean verify(LoginObject lo){
if(lo.getCode().equals("lucas") && lo.getPassword().equals("12345")){
return true;
}else{
return false;
}
}
#PostMapping(value = "login")
public ResponseEntity<?> verifyLogin(#RequestBody String login){
System.out.println("LOGIN REALIZADO");
LoginObject loginO = gson.fromJson(login, LoginObject.class);
if(verify(loginO)){
return new ResponseEntity<Boolean>(true,HttpStatus.OK);
}else{
return new ResponseEntity<Boolean>(false,HttpStatus.OK);
}
}
#GetMapping(value = "/getAluno")
public #ResponseBody ResponseEntity<?> getAluno() {
System.out.println("PEGANDO ALUNO");
Aluno aluno = new Aluno("0001","Lucas Alves de Faria","2018/1","10/12/1995",true,"luke#email.com","(37) 999597899","127.831.956-58","MG-19.319.265");
return new ResponseEntity<Aluno>(aluno, HttpStatus.OK);
}
}
The function verify login in my backend working fine(I'm call this function in other service). But the fontend don't call the other function (getAluno)
I'm not sure about what you mean when you say "But the fontend don't call the other function (getAluno)". You may look at your network calls and verify the calls.
In your front component which calls your service, you need to have a subscribe, something like this :
this.yourService.getAluno().subscribe(
(res: ResponseEntity) => {
this.aluno = res.json;
},
(res: ResponseEntity) => this.onError(res.json)
);
Hope it helps you.
Related
I'm trying to move from traditional approach to Reactive style. Early days for me. One of the challenge I came into and could not make much progress is on model validation. With RestControllers, it was as easy as #Valid.
I don't see anything out there to make it happen for Webflux way of doing things
package com.reactive.sbhello.handler;
import com.reactive.sbhello.model.Order;
import com.reactive.sbhello.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import javax.validation.Validator;
#Component
public class OrderHandler {
#Autowired
private OrderService orderService;
private final Validator validator;
public OrderHandler(Validator validator) {
this.validator = validator;
}
public Mono<ServerResponse> getAll(ServerRequest request) {
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(orderService.getAllOrders(),
Order.class
);
}
public Mono<ServerResponse> getOrderInfo(ServerRequest request) {
var orderId = request.pathVariable("orderId");
var response = orderService.getOrderById(Integer.parseInt(orderId));
return response.collectList()
.flatMap(orders -> {
if(orders.isEmpty()) {
return ServerResponse.badRequest().body(BodyInserters.fromValue("Invalid OrderId"));
} else {
return ServerResponse.ok().body(BodyInserters.fromValue(orders));
}
});
}
public Mono<ServerResponse> addOrder(ServerRequest request) {
return request.bodyToMono(Order.class)
.flatMap(order -> orderService.addOrder(order))
.flatMap(order -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(order)));
}
}
"addOrder" function at the moment lacks any validation. As a result, null values go through. Is there anyway to validate apart from doing it in service and bubble up the error? Or should I stick to RestController approach and still use streaming from there.
Swagger doesn't recognize a new interface of rest api.
This are swagger configuration file.
package trn06.administracion.api.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#Slf4j
#EnableSwagger2
#Configuration
public class TRN06SwaggerConfiguration {
#Value("${custom.host}")
private String hostValue;
private ApiInfo _apiInfo(final String version) {
return new ApiInfoBuilder()
.title("Administrative events")
.termsOfServiceUrl("")
.version(version)
.contact(new Contact("",
"",
""))
.build();
}
private Docket _configureVersion(final String version) {
// Get environment from java environment variables
return new Docket(DocumentationType.SWAGGER_2)
.host(hostValue)
.groupName("Version_" + version)
.select()
.apis(RequestHandlerSelectors.basePackage("trn06.administracion.api.controller.rest"))
.paths(PathSelectors.ant("/v" + version + "/**"))
.build()
.useDefaultResponseMessages(false)
.apiInfo(_apiInfo(version));
}
#Bean
Docket configureV1_0() {
return _configureVersion("1.0");
}
}
All interfaces defined on package trn06.administracion.api.controller.rest are ok, in fact I have two other interfaces mapped ok, except this one:
package trn06.administracion.api.controller.rest;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.GetMapping;
import trn06.administracion.api.model.dto.TRN06ErrorDto;
import trn06.administracion.api.model.dto.TRN06EventsAuthorityDto;
import trn06.administracion.api.model.dto.TRN06ValidationErrorDto;
import java.util.List;
#Api(value = "authorities", description = "Event's authorities ", tags = "Authorities")
public interface TRN06EventsAuthorityApiController {
#ApiOperation(value = "List of authorities", nickname = "findAuthorities", response = TRN06EventsAuthorityDto.class, responseContainer = "List", tags = {"Authorities,"})
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Operation performed", response = TRN06EventsAuthorityDto.class, responseContainer = "List"),
#ApiResponse(code = 400, message = "Validation error", response = TRN06ValidationErrorDto.class),
#ApiResponse(code = 404, message = "Not found"),
#ApiResponse(code = 500, message = "Error", response = TRN06ErrorDto.class)})
#GetMapping(value = "/v1.0/authorities",
produces = "application/json")
List<TRN06EventsAuthorityDto> findAuthorities();
}
Looks like database entity it's ok, I try making an error and was detected correctly. Try changing RequestHandlerSelectors to any(), same results.
No idea and no clue of whats appening.
Kind regards
You need to create an implementation of this interface and add #RestController and #RequestMapping annotations in the implementation.
For example:
#RestController
#RequestMapping("/findAuthorities")
public class TRN06EventsAuthorityApiControllerImpl implements TRN06EventsAuthorityApiController {
#Override
public List<String> findAuthorities() {
return null;
}
}
In my case, was an annotation I forgot
public class TRN06EventsTypesApiControllerImpl
implements TRN06EventsTypesApiController {
....
After put anotation #RestController was fine
#RestController
public class TRN06EventsTypesApiControllerImpl
implements TRN06EventsTypesApiController {
....
Anyway, I take the note of #RequestMapping annotation.
Thanks #v-mokrecov and #mahesh-loya
I'm getting this error:
core.js:1448 ERROR SyntaxError: Unexpected end of JSON input
I think the error is in the response , how i can correct create a #responseBody
for the front to understand that the object in the back end is created properly
the input is (license:"gd345") without the parentheses
Component file:
import { Component, OnInit } from '#angular/core';
import { Http, Headers } from '#angular/http';
#Component({
selector: 'posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.css']
})
export class PostsComponent {
posts: any[];
letter: any;
constructor(private http: Http) {
http.get('http://localhost:8183/api/vehiculespark')
.subscribe(response => {
this.posts = response.json();
});
}
createPost(input: HTMLInputElement) {
debugger;
let post = { license: input.value };
this.letter = post;
const headers = new Headers({ 'Content-Type': 'application/json' });
this.http.post('http://localhost:8183/api/vehicules', this.letter, { headers: headers })
.subscribe(response => {
console.log(response.json())
});
debugger;
}
}
spring Controller:
package com.api.kingspark.parking.controller;
import com.api.kingspark.parking.domain.Tickect;
import com.api.kingspark.parking.domain.Vehicule;
import com.api.kingspark.parking.repositories.TicketRepository;
import com.api.kingspark.parking.repositories.VehiculoRepository;
import com.api.kingspark.parking.services.PorteroServices;
import org.reactivestreams.Publisher;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.APPLICATION_XML_VALUE;
#RestController
public class ParkingController {
private PorteroServices porteroServices;
private final VehiculoRepository vehiculoRepository;
private final TicketRepository ticketRepository;
public ParkingController(PorteroServices porteroServices, VehiculoRepository vehiculoRepository, TicketRepository ticketRepository) {
this.porteroServices = porteroServices;
this.vehiculoRepository = vehiculoRepository;
this.ticketRepository = ticketRepository;
}
#CrossOrigin
#GetMapping("/api/vehiculespark")
List<Tickect> listIn(){
return porteroServices.getInVehicules();
}
#GetMapping("/api/vehicules")
Flux<Vehicule> listAll(){
return vehiculoRepository.findAll();
}
#GetMapping("/api/vehicules/{id}")
Mono<Vehicule> getById(#PathVariable String id){
return vehiculoRepository.findById(id);
}
#CrossOrigin
#ResponseStatus(HttpStatus.CREATED)
#PostMapping(value = "/api/vehicules",consumes="application/json",produces={"application/json","application/xml"})
#ResponseBody
Mono<Void> createVehicule(#RequestBody Publisher<Vehicule> carstream){
Vehicule ca= Mono.fromDirect(carstream).cache().block();
return porteroServices.saveVehicule(ca);
//return ResponseEntity.created(location).build();
}
#PutMapping("/api/vehicules/{id}")
Mono<Tickect> update(#PathVariable String id, #RequestBody Vehicule vehicule){
return ticketRepository.save(porteroServices.drawVehicule(id));
}
}
I have a problem with the PAX-Web. I've tried to register a Websocket service as declrarative, but it is unaccessible from web. I've tried the given websocket-jsr356-6.0.3.war and it works fine. As I see the WAR file handles differently the org.osgi.service.http.HttpContext. I've tried the following scenarios:
Scenario 1 - OSGi R6 Whiteboard HTTP method
Creating a ServletContextHelper:
package hu.blackbelt.judo.common.rest.regular;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
#Component(immediate = true)
#Service(ServletContextHelper.class)
#Properties(value = {
#Property(name = HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, value = "chat"),
#Property(name = HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, value = "/test")
})
public class ChatServletContext extends ServletContextHelper {
}
And adding the Websocket Endpoint:
package hu.blackbelt.judo.common.rest.regular;
import lombok.extern.slf4j.Slf4j;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
#Component(immediate = true)
#Service(Object.class)
#Properties(value = {
#Property(name = HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
value = "=(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=chat)")
})
#Slf4j
public class ChatEndpoint {
public static final String ROOM = "room";
#OnOpen
public void onOpen(final Session session, #PathParam(ROOM) final String room) {
LOGGER.info("session openend and bound to room: " + room);
session.getUserProperties().put(ROOM, room);
}
#OnMessage
public void onMessage(final Session session, final ChatMessage chatMessage) {
String room = (String) session.getUserProperties().get(ROOM);
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& room.equals(s.getUserProperties().get(ROOM))) {
s.getBasicRemote().sendObject(chatMessage);
}
}
} catch (IOException | EncodeException e) {
LOGGER.warn("onMessage failed", e);
}
}
}
The logs show me that the Endpoint is catched. I've debugged and Pax-Web is registering it.
The log shows the following line:
2017-05-04 02:36:02,698 | INFO | Thread-70 | WebSocketTracker | 330 - org.ops4j.pax.web.pax-web-extender-whiteboard - 6.0.3 | found websocket endpoint!!
But the websocket is unaccessible with the following URL: ws://localost:8181/test/chat/testroom
Scenario 2 - Pax-Web properties on registered HttpContext (with JAX-RS it works)
Creating HttpContext instance: (Utilizing the OSGi given Helper abstract class):
package hu.blackbelt.judo.common.rest.regular;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.context.ServletContextHelper;
#Component(immediate = true)
#Service(HttpContext.class)
#Properties(value = {
#Property(name = "httpContext.id", value = "chat"),
#Property(name = "httpContext.path", value = "test")
})
public class ChatHttpContext extends ServletContextHelper implements HttpContext {
}
And the Websocket Endpoint:
package hu.blackbelt.judo.common.rest.regular;
import lombok.extern.slf4j.Slf4j;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
#SuppressWarnings({"checkstyle:missingctor", "checkstyle:illegaltoken"})
#Component(immediate = true)
#Service(Object.class)
#Properties(value = {
#Property(name = "httpContext.id", value = "chat")
})
#ServerEndpoint(value = "/chat/{room}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class)
#Slf4j
public class ChatEndpoint {
public static final String ROOM = "room";
#OnOpen
public void onOpen(final Session session, #PathParam(ROOM) final String room) {
LOGGER.info("session openend and bound to room: " + room);
session.getUserProperties().put(ROOM, room);
}
#OnMessage
public void onMessage(final Session session, final ChatMessage chatMessage) {
String room = (String) session.getUserProperties().get(ROOM);
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& room.equals(s.getUserProperties().get(ROOM))) {
s.getBasicRemote().sendObject(chatMessage);
}
}
} catch (IOException | EncodeException e) {
LOGGER.warn("onMessage failed", e);
}
}
}
But the websocket is unaccessible with the following URL: ws://localost:8181/test/chat/testroom
How can I achive that webcsocket be available? I do not want to repackage my bundle as WAB. Is there any way?
I have following method in my rest service:
#POST
#Path("/create")
#ResponseStatus(HttpStatus.CREATED)
#Consumes(MediaType.WILDCARD)
public String create( .... ) {.... return json;}
so I want to get a response with json in body and status code CREATED.
The problem is: I can't get a response the CREATED status.
The status code is allways OK, so it seems that "#ResponseStatus(HttpStatus.CREATED)" is just ignored...
Can somebody help me with it?
I'm using hibernate 4.1, spring 3.1 and resteasy 2.3
As far as I know, it's not possible to achieve this by annotating the method with #org.springframework.web.bind.annotation.ResponseStatus.
You can return javax.ws.rs.core.Response from your method:
return Response
.status(Response.Status.CREATED)
.entity("ok")
.build();
Or you can have org.jboss.resteasy.spi.HttpResponse injected, and set the status code directly.
There might be more ways of doing this, but I'm only aware of these two.
Working testcase:
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.interception.PostProcessInterceptor;
import org.junit.Assert;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
public class ResponseTest {
#Path("/")
public static class Service {
#Context HttpResponse response;
#GET
#Path("/1")
public Response createdUsingResponse() throws NotFoundException {
return Response
.status(Response.Status.CREATED)
.entity("ok")
.build();
}
#GET
#Path("/2")
public String created() throws NotFoundException {
response.setStatus(Response.Status.CREATED.getStatusCode());
return "ok";
}
}
public static class Interceptor implements PostProcessInterceptor {
#Context HttpResponse response;
#Override
public void postProcess(ServerResponse response) {
if(this.response.getStatus() != 0){
response.setStatus(this.response.getStatus());
}
}
}
#Test
public void test() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(new Service());
dispatcher
.getProviderFactory()
.getServerPostProcessInterceptorRegistry()
.register(new Interceptor());
{
MockHttpRequest request = MockHttpRequest.get("/1");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals(201, response.getStatus());
}
{
MockHttpRequest request = MockHttpRequest.get("/2");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals(201, response.getStatus());
}
}
}