I have a java-springboot microservice running on port 8080 and localhost server. It looks like this :
#RequestMapping("/user")
#RestController
public class UserController {
#Autowired
UserService userService;
#RequestMapping(method = RequestMethod.GET, value = "")
public User getUser() {
return userService.getUser();
}
}
I am trying to access the User data using the call "http://localhost:8080/user". While testing it through the browser and Postman the call is returning the data. But with javacript it is returning an empty response.
I am a newBee in js.
My javascript code loks like this:
function getCurrentUser()
{
try
{
var userUrl = "http://127.0.0.1:8080/user";
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
try
{
if (this.readyState == 4 ) {
var response = this.responseText;
document.getElementById("idCurrentName").innerHTML = response;
}
}
catch(erMs)
{
document.getElementById("idCurrentName").innerHTML = erMs;
}
};
xhttp.open("GET", userUrl, true);
xhttp.setRequestHeader('Content-Type', 'text/plain');
xhttp.send();
}
catch(erMsg)
{
document.getElementById("idCurrentName").innerHTML = erMsg;
}
}
Please help in accessing the data on loclhost.
Thanks!!
The issue was actually related to CORS. I initially added a chrome browser extension, but then as I am using SpringBoot in the backend for my services, I added the annotation #CrossOrigin on my RestController. That fixed the CORS problem.
Hope it helps.
The backend code now looks like this:
#CrossOrigin
#RequestMapping("/user")
#RestController
public class UserController {
#Autowired
UserService userService;
#RequestMapping(method = RequestMethod.GET, value = "")
public User getUser() {
return userService.getUser();
}
}
Related
I am trying to implement Filepond image uploader into my ASP.net Core 5 web application using the entity framework.
I am having trouble saving the uploaded images to the server.
The post request to the Api controller errors with a 415 "Unsupported Media type" error.
The code from the Api Controller constructor gets hit, but not the code within the Create method.
javascript file:
const inputElement = document.querySelector('input[type="file"]');
const pond = FilePond.create(inputElement);
FilePond.setOptions({
server: {
url: "/SaveImage/",
process: (fieldName, file, metadata, load, error, progress, abort) => {
const formData = new FormData();
formData.append(fieldName, file, file.name);
formData.append("CaseId", "#Model.CaseId");
const request = new XMLHttpRequest();
request.open('POST', '/SaveImage/');
request.upload.onprogress = (e) => {
progress(e.lengthComputable, e.loaded, e.total);
};
request.onload = function () {
if (request.status >= 200 && request.status < 300) {
load(request.responseText);
}
else {
error('Error during Image Upload');
}
};
request.send(formData);
return {
abort: () => {
request.abort();
abort();
}
};
},
}
})
Api Controller:
[Route("[controller]")]
[ApiController]
public class saveImageController : ControllerBase
{
private readonly NoPainNoGameDbContext _context;
public saveImageController(NoPainNoGameDbContext context)
{
_context = context;
}
[HttpPost]
public async Task<ActionResult> Create([FromForm] Models.GameImage doc, [FromForm] List<IFormFile> files)
{
if (files != null && doc.CaseId != 0)
{
foreach (var file in files)
{
doc.Guid = Guid.NewGuid().ToString();
doc.ImageName = file.FileName.Split('.').FirstOrDefault();
doc.FileType = file.FileName.Split('.').LastOrDefault().ToLower();
doc.CreatedOn = DateTime.Now;
doc.FileSize = file.Length;
_context.GameImages.Add(doc);
await _context.SaveChangesAsync();
}
return Ok(doc.Guid);
}
else
{
return BadRequest("The file is null");
}
}
}
Input
<input type="file" multiple class="filepond" id="imageUploader" name="files">
I've never used FilePond before but I managed to reproduce your problem with the code you provided. All you need to do is use the [FromForm] attribute on your action parameters i.e.
public async Task<ActionResult> Create([FromForm] Models.GameImage doc, [FromForm] List<IFormFile> files)
You haven't provided what your input[type='file'] looks like, but it should also have a name attribute that matches the action parameter files (List<IFormFile> files), i.e. your input[type='file] should have a name='files' attribute (if it doesn't already).
Also, I wouldn't suggest passing your entities as an action parameter, it tends to become problematic as your project progresses. Instead you should use a DTO, What is a Data Transfer Object (DTO)?
I work on web application and encountered an issue with fetching data from an endpoint using Java Script. If I type endpoint adres in a browser it works perfectly fine but somehow it does not work in the script. The response.ok is returns False.
Here is script:
(function() {
function requestAuthorization() {
let response = fetch("http://localhost:8080/authorizationData")
.then(response => response.json());
if (response.ok) {
let json = response.json();
alert(json);
} else {
alert("HTTP response not ok");
}
}
requestAuthorization();
})();
Here is controller:
#RestController
class AuthController {
private final AuthService service;
AuthController(AuthService service) throws IOException {
this.service = service;
}
#GetMapping("/authorizationData")
public ResponseEntity<AuthData> authorize() throws IOException {
return ResponseEntity.ok(service.getAuthData());
}
}
Here is service:
#Service
class AuthService {
private final ObjectMapper mapper;
AuthService(ObjectMapper mapper) {
this.mapper = mapper;
}
public AuthData getAuthData() throws IOException {
String resourcePath = "data/applicationSettings.json";
InputStream resource = new ClassPathResource(resourcePath).getInputStream();
return mapper.readValue(resource, AuthData.class);
}
}
What is wrong? If You have any other advice regarding my work I will be pleased to hear it.
EDIT
The script and and HTML file which runs it are both located in static directory in classpath.
You should be doing it like this:
// mark your function as async
async function requestAuthorization() {
// always try using const rather than let
const response = await fetch("http://localhost:8080/authorizationData");
if (response.ok) {
const json = response.json();
alert(json);
} else {
alert("HTTP response not ok");
}
}
I am trying to implement a spring boot chat application using WebSocket stomp client. If I send messages from one device to 4,5 devices then some are getting the messages and some are not. Some can send messages but don't receive any message and some are working completely fine. My application is running on wildfly server and the URL is over https.
Here is my js file. From my JSP page I am calling sendMsg with all parameter and through render method I am attaching the response with JSP using Handlebars.
if (!window.location.origin) {
window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
}
const url = window.location.origin+contextPath;
let stompClient;
let selectedUser;
let newMessages = new Map();
function connectToChat(userName, topicName) {
console.log("connecting to chat...")
let socket = new SockJS(url + '/chat');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log("connected to: " + frame);
stompClient.subscribe("/topic/decision-log", function (response) {
let data = JSON.parse(response.body);
var msg = data.message;
var fromlogin = data.message;
render(data.username, msg, fromlogin);
});
});
}
connectToChat("1", "decision-log");
function sendMsg(from, text, username) {
stompClient.send("/app/chat/" + from, {}, JSON.stringify({
fromLogin: from,
message: text,
topicName: topicName,
username: username
}));
}
function render(username, message, projectId) {
var templateResponse = Handlebars.compile($("#message-response-template").html());
var contextResponse = {
username: username,
response: message,
date: date,
projectId: projectId
};
setTimeout(function () {
$chatHistoryList.append(templateResponse(contextResponse));
scrollToBottom();
}.bind(this), 1500);
}
Here is my WebSocket configuration file:
#Configuration
#EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer{
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app").enableSimpleBroker("/topic");
}
}
This is the controller. I always save all messages on the database that are coming through WebSocket that's why I can be sure that all devices can send messages as they have been saved on the database.
#Controller
#AllArgsConstructor
public class MessageController {
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
private final DecisionLogService decisionLogService;
#MessageMapping("/chat/{to}")
public void sendMessage(#DestinationVariable String to, MessageModel message, Authentication authentication ) {
simpMessagingTemplate.convertAndSend("/topic/decision-log", message);
AuthResponse userDetails = (AuthResponse) authentication.getDetails();
DecisionLogCreateRequest decisionLogCreateRequest = new DecisionLogCreateRequest();
decisionLogCreateRequest.setDecision(message.getMessage());
decisionLogCreateRequest.setProjectId(to);
ServiceResponseExtended<Boolean> response = decisionLogService.addDecisionLog(userDetails.getAccessToken(), decisionLogCreateRequest);
}
}
I can not find anything similar this issue. Please help me with right information and suggestion, and if anyone faced same kind of problem please share with me.
The problem was solved after configuring RabbitMQ Stomp Broker as a message broker instead of SimpleBroker.
Current WebSocket configuration:
#Configuration
#EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer{
#Value("${stomp-broker-relay-host}")
private String RELAY_HOST;
#Value("${stomp-broker-relay-port}")
private String RELAY_PORT;
#Value("${stomp-broker-login-user}")
private String USER;
#Value("${stomp-broker-login-pass}")
private String PASS;
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableStompBrokerRelay("/topic").setRelayHost(RELAY_HOST).setRelayPort(Integer.parseInt(RELAY_PORT)).setClientLogin(USER)
.setClientPasscode(PASS);
}
}
Reference:
https://medium.com/#rameez.s.shaikh/build-a-chat-application-using-spring-boot-websocket-rabbitmq-2b82c142f85a
https://www.javainuse.com/misc/rabbitmq-hello-world
I have my angular service like:
GetPaymentDeadlineExtension(data: PatientInput): Observable<any> {
return this.httpClient.post<any>(
this.root + `/api/PaymentDeadline/RegisterPatientInput`,data);
}
in my web api controller:
[Route("RegisterPatientInput")]
public SrvInvoiceCompositView[] RegisterGetPaymentDeadlineExtension(PatientInput data)
{
SrvInvoiceCompositView[] list = null;
string ContractNo = String.Empty;
string DktInvoiceNo = String.Empty;
try
{
ContractNo = data.BillNumber.Split('-')[0];
DktInvoiceNo = data.BillNumber.Split('-')[1];
list = DkService.SrvFindInvoiceCompositViewDentaPay(DktInvoiceNo, data.Amount, data.PatientNumber, ContractNo);
}
catch(Exception ex)
{
// exception to be returned to angular app.
}
return list;
}
and in my component.ts file:
this.homePageService.GetPaymentDeadlineExtension(this.input).subscribe(
data=>
{
this.patientInfo = data;
},
error=>
{
//i want to get my ex.message here, so i can display it
}
)
this.homePageService.GetPaymentDeadlineExtension(this.input)
.pipe(catchError((error)=> { handleError here}).subscribe(
data=>
{
this.patientInfo = data;
}
)
More info: https://www.learnrxjs.io/learn-rxjs/operators/error_handling/catch
To get an error in RxJS subscribe method you have to return such a http response that doesn't have 2xx status code. Based on your code snippet Bad Request (400) could be a good choice for example. So on .NET Core side you need to return an IActionResult following way:
[Route("RegisterPatientInput")]
public IActionResult RegisterGetPaymentDeadlineExtension(PatientInput data)
{
SrvInvoiceCompositView[] list = null;
string ContractNo = String.Empty;
string DktInvoiceNo = String.Empty;
try
{
ContractNo = data.BillNumber.Split('-')[0];
DktInvoiceNo = data.BillNumber.Split('-')[1];
list = DkService.SrvFindInvoiceCompositViewDentaPay(DktInvoiceNo, data.Amount, data.PatientNumber, ContractNo);
return Ok(list); // This is has http status code 200 in the http response
}
catch(Exception ex)
{
return BadRequest(ex.Message); // This has http status code 400 in the http response
}
}
If you put in the Angular Component file following:
this.homePageService.GetPaymentDeadlineExtension(this.input).subscribe(
data=>
{
this.patientInfo = data;
},
error=>
{
console.log(error);
}
)
After a http request you will be able to see the exception message from the backend in the browser console.
I don't know exactly the use case of the developed software, but it is not recommended to display the exception on the frontend side in production. A hacker could extract some information from the server code with causing intentionally exceptions.
I have spring boot service which provides csv file as response.
How do we call this service from angular 5 typescript.
download of a file should happen depends on some input parameters so I will have post call with user clicks the export button.
below is the rest code in controller.
#Controller
public class MyController {
#RequestMapping(value = "/downLoadDataQueryCsv", method = RequestMethod.GET)
public ResponseEntity<Object> downLoadDataQueryCsv(Model model) throws IOException {
FileWriter fileWriter = null;
try {
DataQueryRequestParams dataQueryRequestParams = new DataQueryRequestParams();
dataQueryRequestParams.setMbuCategory("UKY");
// Result table.
List<OrderIdFinalRank> rankList = // call api to get data.
// construct headers
List<String> csvHeaders = constructDataQueryHeaders();
StringBuilder fileContent = new StringBuilder(String.join(",", csvHeaders));
fileContent.append("\n");
// construct file content from response
for(OrderIdFinalRank finalRank : rankList) {
fileContent.append(StringUtils.join(constructDataQueryRow(finalRank), ",")).append("\n");
}
String fileName = new String("DataQueryTab.csv");
fileWriter = new FileWriter(fileName);
fileWriter.write(fileContent.toString());
fileWriter.flush();
File file = new File(fileName);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
ResponseEntity<Object> responseEntity = ResponseEntity.ok().headers(headers).contentLength(file.length())
.contentType(MediaType.parseMediaType("application/txt")).body(resource);
return responseEntity;
} catch (Exception e) {
System.out.println("Exception: " +e);
return new ResponseEntity<>("Error occurred", HttpStatus.INTERNAL_SERVER_ERROR);
} finally {
if(null != fileWriter) {
fileWriter.close();
}
}
}
}
Now I need to call this from UI when I click export button, what have written is below.
I have read file saver and added below code, but its not working. kindly help me.
#Injectable()
export class ApiService {
onExport(dataQueryRequestParams: any) {
const dataQueryURL = API_URL + '/downLoadDataQueryCsv';
const body = JSON.stringify(dataQueryRequestParams);
this._http.get(dataQueryURL).subscribe(res => {
saveAs(res, 'data.csv');
});
}
}
Note: When I ran rest URL from browser the file is downloaded, but the same needs to happen when I click export button.
Am new to UI technologies.
Thanks
I have fixed problem with below code.
export class ApiService {
onExport(requestParams: any): Observable<any> {
const dataQueryURL = API_URL + '/downLoadDataQueryCsv';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'Application/json; charset=UTF-8'
}),
responseType: 'text' as 'text'
};
const body = JSON.stringify(requestParams);
return this._http.post(dataQueryURL, body, httpOptions);
}
}
added below in caller Component class.
export class Component implements OnInit {
onExport() { this._apiService.onExport(this.dataQueryForm.value).subscribe(data => {
const blob1 = new Blob([data], { type: 'text/csv' });
FileSaver.saveAs(blob1, 'data.csv');
}) ;
}
}
Thank you all for your responses !