in my angular js code I have date as string:
self.submit = function () {
console.log("in voice prompt component - submit");
console.log(self.voice);
self.fromDate = new Date(self.fromDate);
$http.put('http://localhost:8082/api/Voices/updateVoice', self.fromDate).then(
function successCallback(response) {
self.voices = response.data;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(response);
});
}
I want to send it to my server: LocalDate from Java 8
#Path("/updateVoice")
#PUT
#Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public void updateVoice(LocalDate fromDate) throws Exception {
but i get an error:
Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value ('2017-04-04T21:00:00.000Z')
Related
I’m having an issue with my project. In my angularjs controller a function is being executed and then my function to make a call to my database to update a record is executing without waiting for the first function to complete and therefore sending over an undefined result variable.
Below you can find my code snippets with my attempts so far.
Submit button function:
$scope.submitNewStarters = function () {
// result is returning as undefined <<<<< Issue
var result = $scope.sendNewStarterDetailsToApi();
$scope.updateArchivedImportFlag(result);
};
Controller function handling the logic:
$scope.sendNewStarterDetailsToApi = function () {
swal({
title: "Confirmation",
text: "Are you sure you want to import the new starter details?",
icon: "info",
dangerMode: true,
buttons: ["No", "Yes"]
}).then(function (approve) {
if (approve) {
// Get each of the new starter details that have been set to true for import.
var newStartsToImport = $scope.tableParams.data.filter(x => x.imported == true);
for (let i = 0; i < newStartsToImport.length; i++) {
// Parses the current new starter object into a stringified object to be sent to the api.
$scope.newStartsToImport = $scope.createApiObject(newStartsToImport[i]);
// A check to ensure that nothing has went wrong and that the stringify object has worked.
if ($scope.newStartsToImport !== "") {
apiFactory.postNewStarterDetailsToApi($scope.newStartsToImport).then(function (response) {
var isSuccessful = response.data.d.WasSuccessful;
if (isSuccessful)
toastr.success("New starter details successfully sent to API.", "Success!");
else {
var errorMessage = response.data.d.ErrorMessage;
toastr.error("New starter details were unsuccessfully sent to API. Please try again. \n" + errorMessage, "Error!");
}
});
}
else {
toastr("An error has occurred when attempting to create the data object to be sent to API. The process has stopped!", "Error!");
break;
}
}
return newStartsToImport;
}
else
toastr.info("No new starter details were sent to API", "Information!");
});
};
Factory function for API call:
postNewStarterDetailsToApi: function (data) {
return $http({
url: "https://www.example.com/services/service.svc/Import",
method: "POST",
data: data,
headers: {
'Content-Type': 'application/json; charset=utf-8',
}
}).then(function successCallbwack(response) {
// this callback will be called asynchronously
// when the response is available
return response;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('An error has occured during the function call postNewStarterDetailsToApi(): ', response);
});
}
So with the concept of promises how am I able to execute the sendNewStarterDetailsToApi function, wait for it to complete and then return the populated array? Once the populated array (result) is returned then execute the updateArchivedImportFlag function.
Below I've added an illustration of what I'd like to achieve:
The approach I am using is , save all the promises in an array .
Use any promise library or es6 Promise, and use .all function to wait for all promises to execute
The syntax i wrote is not totally correct. Since you are using angular js , you can use $q.all
$scope.sendNewStarterDetailsToApi = function () {
swal({
title: "Confirmation",
text: "Are you sure you want to import the new starter details?",
icon: "info",
dangerMode: true,
buttons: ["No", "Yes"]
}).then(function (approve) {
var res = [];
if (approve) {
// Get each of the new starter details that have been set to true for import.
var newStartsToImport = $scope.tableParams.data.filter(x => x.imported == true);
for (let i = 0; i < newStartsToImport.length; i++) {
// Parses the current new starter object into a stringified object to be sent to the api.
$scope.newStartsToImport = $scope.createApiObject(newStartsToImport[i]);
// A check to ensure that nothing has went wrong and that the stringify object has worked.
if ($scope.newStartsToImport !== "") {
res.push(apiFactory.postNewStarterDetailsToApi($scope.newStartsToImport))
}
else {
toastr("An error has occurred when attempting to create the data object to be sent to API. The process has stopped!", "Error!");
break;
}
}
return Promise.all(res);
}
else
toastr.info("No new starter details were sent to API", "Information!");
}).then(function (data) {
data.forEach((response) => {
var isSuccessful = response.data.d.WasSuccessful;
if (isSuccessful)
toastr.success("New starter details successfully sent to API.", "Success!");
else {
var errorMessage = response.data.d.ErrorMessage;
toastr.error("New starter details were unsuccessfully sent to API. Please try again. \n" + errorMessage, "Error!");
}
})
}).then((res) => {
//call Submit new starters
})
};
This will be a post where I ask the question and propose a solution
Since having had several trouble and having looked around a lot I decided to post my final solution for anyone else to take profit from it.
Question:
How to render google's reCaptcha v2.0 widget and verifying it in a Marionettejs app with a java back end.
After the common steps and following google guides to render the re captcha my captcha still didn't render, so here comes my solution:
Rendering the captcha and the inclusion of the script are both made inside the itemview onRender function:
'text!login/templates/form.html',
'app'
], function (app, Marionette, Backbone, _, $, Handlebars, FormTemplate) {
return Marionette.ItemView.extend({
template: Handlebars.compile(FormTemplate),
ui: {
form: '
},
events: {
'submit #ui.form': 'onSubmit'
},
onRender: function() {
this.loadCaptcha();
},
loadCaptcha: function() {
var self = this;
var getRecaptchaResponse = function(response) {
self.captchaResponse = response;
};
window.renderCaptcha = function () {
self.captchaWidgetId = grecaptcha.render('yourCaptchaDiv', {
sitekey: 'YourSiteKey',
callback: getRecaptchaResponse
});
};
$.getScript('https://www.google.com/recaptcha/api.js?onload=renderCaptcha&render=explicit', function() {});
},
...
}
I tried other ways of loading the script with several errors, like the script loaded before the div for it, or the browser says de Dom has completely loaded but the onRender gets called after
I had to include a div for the captcha widget to load in, this is in
form.html
<div id="reCaptcha" class="btn"></div>
That will have your widget rendered, now you need to both verify it has been filled and it is a valid user response with google, for this I use the same module and use the next function:
onSubmit: function (e) {
//only act if the captcha has been filled - This could be easily erased from a browser, but a back end verification takes place too
if (grecaptcha.getResponse() !== "") {
e.preventDefault();
var _view = this;
this.blockForm();
$.ajax({
url: 'yourLoginService',
type: 'POST',
data: {
userLogin: this.ui.user.val(),
userPassword: this.ui.password.val(),
//get the captcha response
captchaResponse: grecaptcha.getResponse()
}
}).done(function (data) {
app.router.navigate('', {trigger: true});
_view.destroy();
}).fail(function (jqXHR, textStatus, errorThrown) {
// your fail handling
});
}
},
Then comes the time to verify your captcha server side using the secret key provided by google (note this is a Java6 app, therefore the clumbersome exception Handling):
//some other imports ignored
import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;
class Captcha {
private static final String CAPTCHA_SECRET_KEY = "YourSecretKey";
private static final Logger LOGGER = Logger.getLogger(Captcha.class);
static boolean isCaptchaValid(String response) {
try {
String url = "https://www.google.com/recaptcha/api/siteverify?"
+ "secret=" + CAPTCHA_SECRET_KEY
+ "&response=" + response;
InputStream res = new URL(url).openStream();
JSONObject json = new JSONObject(getJsonResponse(res));
res.close();
return json.getBoolean("success");
} catch (JSONException e) {
LOGGER.error("Can not parse captcha response Json: " + e);
return false;
} catch (MalformedURLException e) {
LOGGER.error("Malformed URL: " + e);
return false;
} catch (IOException e) {
LOGGER.error("Error reading response from captcha verification response: " + e);
return false;
}
}
private static String getJsonResponse(InputStream res) throws IOException {
BufferedReader rd = new BufferedReader(new InputStreamReader(res, Charset.forName("UTF-8")));
/*TODO in java 8+ use this and avoid using the external library
return rd.lines().collect(Collectors.joining());
*/
return IOUtils.toString(rd);
}
}
This is my JS code to receive a message from Azure Service Bus
function receiveMessage(serviceBusTopic, serviceBusSubscriber, callback) {
serviceBus.receiveSubscriptionMessage(serviceBusTopic, serviceBusSubscriber,
{ isPeekLock: true }, function (error, lockedMessage) {
if (!error) {
try {
const receivedMessage = JSON.parse(lockedMessage.body);
console.log('receivedMessage', receivedMessage);
if (!_.isEqual(receivedMessage.Type, messageType.USERPROFILES_USER_UPDATED)) {
return;
}
//Message received and locked
callback(receivedMessage);
serviceBus.deleteMessage(lockedMessage, function (deleteError) {
if (!deleteError) {
// Message deleted
console.log('message has been deleted.');
}
});
}
catch (error) {
console.log('Start debugging');
console.log(lockedMessage.body);
}
When I receive a message it has strange encoding and JSON.parse throws an exception.
The lockedMessage output is:
{ body: '#\fbase64Binary\b3http://schemas.microsoft.com/2003/10/Serialization/�s\u0002{"Type":"SomeEvent"�\u0001}',
brokerProperties:
{ DeliveryCount: 9,
EnqueuedSequenceNumber: 0,
EnqueuedTimeUtc: 'Thu, 16 Nov 2017 23:50:16 GMT',
LockToken: '6e3e311f-0fe9-4366-844d-18046fd000db',
LockedUntilUtc: 'Fri, 17 Nov 2017 00:10:46 GMT',
MessageId: 'nil',
PartitionKey: '1d84084f-65af-4a33-bb30-62d97d85557d',
SequenceNumber: 61643019899633670,
SessionId: '1d84084f-65af-4a33-bb30-62d97d85557d',
State: 'Active',
TimeToLive: 1566804.069 },
location: '',
contentType: 'application/xml; charset=utf-8',
customProperties: { 'strict-transport-security': NaN, connection: NaN } }
The message is coming from a .NET Core service and that service sends with this code:
var payload = JsonConvert.SerializeObject(SomeEvent);
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
topicClient.SendAsync(serviceBusMessage).Wait();
Why is Node.js not able to parse the message? Another .NET app can receive the same message without any issues.
To avoid this, you need to set ContentType to text/plain when sending a message from .NET Core service. So it should be something like this:
var payload = JsonConvert.SerializeObject(SomeEvent);
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload))
{
ContentType = "text/plain"
};
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
topicClient.SendAsync(serviceBusMessage).Wait();
In this article, they explained the problem and the solution for .NET.
Update:
After some diving, this would not happen to me when I either use .NET Core or .NET to send a message with the standard library Microsoft.Azure.ServiceBus whether ContentType is specified or not.
This is my C# code to send a message:
class Program
{
static void Main(string[] args)
{
string connectionString = "Endpoint=sb://...";
var client = new TopicClient(connectionString, "MyTopic");
var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello core!!! {DateTime.Now}" });
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
client.SendAsync(serviceBusMessage).Wait();
}
private class DemoMessage
{
public DemoMessage()
{
}
public string Title { get; set; }
}
}
This is my Node.js code to receive a message:
var azure = require('azure');
var serviceBusService = azure.createServiceBusService("Endpoint=sb://...");
serviceBusService.receiveSubscriptionMessage('MyTopic', 'sub1', { isPeekLock: true }, function(error, lockedMessage) {
if(!error) {
console.log(lockedMessage);
serviceBusService.deleteMessage(lockedMessage, function (deleteError){
if(!deleteError){
// Message deleted
console.log('message has been deleted.');
}
})
}
});
The lockedMessage output is:
This only happens when I use .NET and the SDK WindowsAzure.ServiceBus with this code:
class Program
{
static void Main(string[] args)
{
string connectionString = "Endpoint=sb://...";
var client = TopicClient.CreateFromConnectionString(connectionString, "MyTopic");
var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello core!!! {DateTime.Now}" });
var serviceBusMessage = new BrokeredMessage(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
client.Send(serviceBusMessage);
}
private class DemoMessage
{
public DemoMessage()
{
}
public string Title { get; set; }
}
}
Now, the lockedMessage output is:
So, I think the message you received is sent from another .NET client and I suggest you clear all messages from the topic before you test it in Node.js.
I ran into this issue as well. If you are using Stream Analytics then its compatibility level may be the cause of this issue. Stream Analytics compatibility level 1.0 uses an XML serializer producing the XML tag you are seeing. Compatibility level 1.1 "fixes" this issue.
See my previous answer here: https://stackoverflow.com/a/49307178/263139.
I am following up in the course AngularJS Front to Back with Web API using ASP.net, we are trying to do queries using ODATA so i added this code in the ProductController in the WebAPI
// GET: api/Products
[EnableQuery()]
public IQueryable<Product> Get()
{
var productRepository = new ProductRepository();
return productRepository.Retrieve().AsQueryable();
}
then added the below code in the productcontroller in the angular code:
function ProductListCtrl(productResource) {
var vm = this;
productResource.query({$skip:1, $top:3}, function (data) {
vm.products = data;
})
but when I try to run it gives me the below error:
angular.js:12701 GET http://localhost:59302//api/products?$skip=1&$top=3 400 (Bad Request)
Possibly unhandled rejection: {"data":{"message":"The query specified in the URI is not valid. No non-OData HTTP route registered.","exceptionMessage":"No non-OData HTTP route registered.",.....
Maybe you don't have odataConfiguration?? Where's you EDM configuration?
In your config file you need something like that:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code:
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
}
Need help with the exception getting whilst posting data to server, although GET method works fine within the same REST Resource. Code is given below; Early attention appreciated.
REST Endpoint
#RestController
#RequestMapping("/trading-api")
public class MemberMessageResource {
private final Logger log = LoggerFactory.getLogger(MemberMessageResource.class);
#Inject
MemberMessageService service;
#RequestMapping(value = "/messages/reply/", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<MemMessage> replyMemeberMessage(#RequestBody MemMessage msg)
throws URISyntaxException {
log.info("REST Request to reply a message : {" + msg.toString() + " }");
MemMessage result = msg;
return new ResponseEntity<MemMessage>(result, HttpStatus.OK);
}
}
MessageService.js
'use strict';
angular.module('nkApp').factory(
'messagesService',
[
'$http',
'$q',
function($http, $q) {
var REST_SERVICE_URI = '/trading-api/messages/';
var factory = {
replyMemeberMessage : replyMemeberMessage
};
return factory;
function replyMemeberMessage(message) {
console.log('Replying Message : ', message);
var deferred = $q.defer();
$http.post(REST_SERVICE_URI + "reply/" + message)
.then(
function (response) {
deferred.resolve(response.data);
},
function(errResponse){
console.error('Error while Replying Message');
deferred.reject(errResponse);
}
);
return deferred.promise;
}
} ]);
Console Error
2017-03-10 23:49:21.515 WARN 11764 --- [nio-8080-exec-8] o.s.web.servlet.PageNotFound : Request method 'POST' not supported
Browser Error
{"timestamp":1489189761519,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/trading-api/messages/reply/[object%20Object]"}
Your message object should not be part of your url, it should be your request body. Instead of adding to the url string, just pass it as the data argument in your angular javascript function:
$http.post(REST_SERVICE_URI + "reply/", message)