I am integrating Google Wallet on my GWT app. At some point (at beginning of JSNI function purchase()), I need to inject API JS code in my app.
<script src="https://sandbox.google.com/checkout/inapp/lib/buy.js"></script>
How can I do it?
public static native void purchase(String token) /*-{
// Success handler
var successHandler = function(status){
if ($wnd.console != undefined) {
console.log("Purchase completed successfully: ", status);
//window.location.reload();
}
}
// Failure handler
var failureHandler = function(status){
if ($wnd.console != undefined) {
console.log("Purchase failed ", status);
}
}
google.payments.inapp.buy({
'jwt' : token,
'success' : successHandler,
'failure' : failureHandler
});
}-*/;
You have to inject the code with a ScriptInjector, because the GWT-code may run within a hidden IFRAME (depends on the used Linker)
Related
I am developing a platform based on the micro services architecture (JAX-RS) and a nodeJS API.
I have a problem adding an object to the database, because it always marks null by spring boot.
*Here is my REST controller code (JAX-RS):
#RequestMapping(value="/Add")
public Actifs AjouterActifs( #RequestBody Actifs act){
return Actif.saveT(act);
}
*Here the code node API to add the object "Actifs":
app.post("/act/add",function (req,res) {
var addActif = JSON.stringify(req.body);
console.log("params: "+addActif);
try {
http.get(url+"/Add",+addActif, function (response) { //problem is here "addActif is null"
var dataJson ='';
response.on('data',function(data){
dataJson += data;
});
response.on('end',function(){
try
{
var addAct = JSON.parse(dataJson);
}
catch(err) {
console.log('erreur de retourner l\'actif -->', +err);
}
res.json(addAct);
});
});
}
catch(e) {
console.log("erreur d'ajouter les info d'actif -->", +e);
}
});
*Postman:
I get this error:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing:
How to avoid a null object passing from node JS to the JAX-RS service ?
thank you for helping me,
You are sending the actif to be added as a query parameter
http.get(url+"/Add?act="+addActif, function (response) {
...
}
But your SpringMVC Endpoint expects to find the Actif object in the request body
#RequestMapping(value="/Add")
public Actifs AjouterActifs( #RequestBody(required=false) Actifs act) {
...
}
Option 1: Use #RequestParameter("act") Actifs act and register an editor to parse the object from the query parameter string (see this question).
Option 2: Actually send the Actif json as the request body, e.g. by performing a POST request to url + "/Add" instead of a GET. You will have to use http.request to implement that.
Furthermore I would suggest to use #RequestBody (without required=false). That ensures that the parameter must be non-null and lets the application fail fast if that is not the case.
I solved the problem by changing the code like this
app.post("/act/add",function (req,res) {
var addActif = JSON.parse(req.body); //parse object
console.log("params: "+addActif);
try {
http.get(url+"/Add",addActif, function (response) { // delete '+'
var dataJson ='';
response.on('data',function(data){
dataJson += data;
});
response.on('end',function(){
try
{
var addAct = JSON.parse(dataJson);
}
catch(err) {
console.log('erreur de retourner l\'actif -->', +err);
}
res.json(addAct);
});
});
}
catch(e) {
console.log("erreur d'ajouter les info d'actif -->", +e);
}
});
I'm trying to call a JavaEE 6 rest service from an Angular factory and I am running into issues.
The java rest service was created by someone else and I'm trying to work off of it and I'm not super-well versed in JavaEE yet, so if you need more info, I'll chip in where I can.
#Path("bills")
public class BillResource {
#EJB
#Resource
private BillableEventBean billableEventBean;
private final BillableEventMapper billableEventMapper = new BillableEventMapper();
BillService implementation not working
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("query")
public List<BillableEventDuplicate> listBillableEvents(BillableEventQueryFilter queryFilter) {
List<BillableEvent> ejbRet = billableEventBean.listBillableEvents(queryFilter.getUserID(),
queryFilter.getBillingTeamID(), queryFilter.getBillStatus(), null);
List<BillableEventDuplicate> ret = billableEventMapper.toBillableEventDuplicateList(ejbRet);
return ret;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{billableEventI}")
public BillableEventDuplicate getBillableEvent(#PathParam("billableEventI") String id) {
BillableEvent ejbRet = billableEventBean.getBillableEvent(id);
BillableEventDuplicate ret = billableEventMapper.toBillableEventDuplicate(ejbRet);
return ret;
}
}
My angular factory for the service looks like this:
'use strict';
var aumBills = angular.module('appBills', ['ngResource']);
appBills.factory('Bills', ['$resource',
function($resource)
{
return $resource('/ua_appcore/api/v1/bills/:billNumber',
{
billNumber:'#billNumber'
},
{
getList: {method: 'POST', params: {'userID':'ABC123'}, url: '/ua_appcore/api/v1/bills/query/'}
});
}]);
The factory in invoked from the controller thusly:
'use strict';
angular.module('app.bills', ['ngRoute','appBills'])
.config(['$routeProvider', function($routeProvider)
{
$routeProvider.
when('/bills',
{
templateUrl: 'bills/bill-list.html',
controller: 'BillListCtrl'
}).
when('/bills/:billId',
{
templateUrl: 'bills/bill-detail.html',
controller: 'BillDetailCtrl'
}).
when('/billsearch',
{
templateUrl: 'bills/bill-search.html',
controller: 'BillSearchCtrl'
});
}])
.controller('BillListCtrl', ['$scope', '$http', '$routeParams', 'Bills',
function($scope, $http, $routeParams, Bills)
{
Bills.getList({},{}).$promise.then(function(billList)
{
$scope.billList = billList;
});
}])
.controller('BillDetailCtrl', ['$scope', '$http', '$routeParams', 'Bills',
function($scope, $http, $routeParams, Bills)
{
Bills.get({},{billNumber: $routeParams.billNumber }).$promise.then(function(bill)
{
$scope.bill = bill;
});
}]);
In my understanding, I needed to create a custom action in the factory to make use of the URL option since there is a POST to get a list of bills back using the same root call. The problem I'm having is that I can't seem to be able to feed any parameters into the queryFilter object even with the Consumes annotation. Am I doing something fundamentally wrong?
First of all you can use chrome plugin Postman to check if your rest service is working correctly if true there is problem with your angular $resource. In my opinion there is missing header "Content-Type=application/json" in your request. I've never use angular in that way you can try to create service like that (this tutorial should be also helpful)
app.service("billsService", function ($resource) {
var bills = $resource("/ua_appcore/api/v1/bills/query");
this.getBills = function () {
var billsResource = new bills();
billsResource.sampleVar = 'value'; // here you can place your vars
return billsResource.$save();
}
});
So, it turns out that it was an infrastructure issue the entire time. We had been deploying to a Websphere Liberty server, and it does not contain the entire WebProfile that JavaEE 6 needs to recognize the rest services. Their may be some work-arounds for it, but the quickest short-term solution is to run a full Websphere server for deployments.
Thanks for the help!
I have a web application with HTML / jQuery which ic connected with AJAX / JSON to a backend system with Java EE / Spring MVC.
In the frontend, a Person can be created by fill in the form fields and then it is submitted and this jQuery code executed:
var person = $(this).serializeObject();
$.postJSON("add/", person, function(data) {
alert("Person with ID "+data.person.id+"' added successfully");
});
In the best case, the Person is created and I'll get a Person object and I can access the values with data.person.*.
Now I want to validate the data which is sent to the backend system and in a case of an error, I want to display in the first step an alert error message.
I did this in the backend system:
#RequestMapping(value="add/", method=RequestMethod.POST)
public #ResponseBody Map<String, ? extends Object> addPerson(#RequestBody Person p, HttpServletResponse response) {
Set<ConstraintViolation<Person>> failures = validator.validate(p);
if (!failures.isEmpty()) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return validationMessages(failures);
} else {
Person person = this.personService.addPerson(p);
return Collections.singletonMap("person", new SerialPerson(person.getId(), person.getName(), ...));
}
}
// internal helpers
private Map<String, String> validationMessages(Set<ConstraintViolation<Person>> failures) {
Map<String, String> failureMessages = new HashMap<String, String>();
for (ConstraintViolation<Person> failure : failures) {
failureMessages.put(failure.getPropertyPath().toString(), failure.getMessage());
System.out.println(failure.getPropertyPath().toString()+" - "+failure.getMessage());
}
return failureMessages;
}
My Person object is annotated, and I get the System.out.println(failure.getPropertyPath().toString()+" - "+failure.getMessage()); on the console, that for example, "name - must be between 1-30 chars"
But how can create an alert message in jQuery in the frontend system?
Thank you in advance for your help & Best Regards.
Update: Link to the Spring MVC AJAX example, where I found the validationMessages method. But there is also no solution how to get the error message.
SOLUTION:
I have to call:
jQuery.ajax({
'type': 'POST',
'url': "add/",
'contentType': 'application/json',
'data': JSON.stringify(person),
'dataType': 'json',
'success': function(data) {alert("success");},
'error': function(xhr) {alert(xhr.responseText);}
});
You can do something like this:
var person = $(this).serializeObject();
$.postJSON("add/", person, function(data) {
if(data.person) {
alert("Person with ID "+data.person.id+"' added successfully");
}
else {
var errors = "";
for(var key in data) if(data.hasOwnProperty(key)) {
errors += data[key] + "\n";
}
alert(errors);
}
});
You shouldn't need to send back a bad request either. Is this what you want?
UPDATE
You can use the code shown in Spring Source, but you'd have to use jQuery.ajax
jQuery.ajax({
type: 'POST',
url: "add/",
data: person,
dataType: "json",
success: function(data) {
alert("Person with ID "+data.person.id+"' added successfully");
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
var errorJSON = JSON.parse(XMLHttpRequest.responseText); //if this is JSON otherwise just alerting XMLHttpRequest.responseText will do
var errors = "";
for(var key in errorJSON) if(errorJSON.hasOwnProperty(key)) {
errors += errorJSON[key] + "\n";
}
alert(errors);
}
});
I'm trying to track pages using Google Analytics within a GWT application.
I already check the following thread: Integrating Google Analytics into GWT application
I think that the solution:
public static native void recordAnalyticsHit(String pageName) /*-{
$wnd.pageTracker._trackPageview(pageName);}-*/;
only works using the synchronous GA script.
I'm trying with the following:
public native void trackHit (String pageName) /*-{
try {
$wnd._gaq.push (['_setAccount', 'UA-XXXXXX-XX']);
$wnd._gaq.push (['_setDomainName', '.mydomain.com']);
$wnd._gaq.push (['_trackPageview', pageName]);
} catch (err) {
alert('failure on gaq' + err);
}
}-*/;
And is not working for me.
Here are my page- and event-tracking functions:
public static native void trackEvent(String category, String action, String label) /*-{
$wnd._gaq.push(['_trackEvent', category, action, label]);
}-*/;
public static native void trackEvent(String category, String action, String label, int intArg) /*-{
$wnd._gaq.push(['_trackEvent', category, action, label, intArg]);
}-*/;
public static native void trackPageview(String url) /*-{
$wnd._gaq.push(['_trackPageview', url]);
}-*/;
I do the _setAccount stuff like normal in the host page (needs to execute before trackPageview() etc will work:
<!-- Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-FAKE1234-2']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
You don't need to use setAccount every time you post an event, only at the beginning. I don't bother with try{}catch{} stuff... I don't actually know JavaScript.
There is a new version of Google Analytics out which uses a new analytics.js script. It's the same process though, just add the script in your html header:
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-YOUR_ACCOUNT-X', 'auto');
ga('send', 'pageview');
</script>
And then can call the new methods like so:
public static native void googleAnalyticsTrackPageView(String url) /*-{
$wnd.ga('send', 'pageview', url);
}-*/;
there is a project on goole code called gwt-gatracker that implement GA function to use in GWT projects. check it out here
I am fiddling around with JBOSS's Web Services, and I have created the following:
http://127.0.0.1:8080/IM/TestService?wsdl
Now I need to access Web Methods from that Web Service from JavaScript.
Say I have a web method named foo in TestService, how do I make an ajax call to it?
I tried accessing the method via http://127.0.0.1:8080/IM/TestService/foo, but I'm getting an HTTP Status 404.
I wrote the following JavaScript that will allow me to call the Web Methods from the JBoss Web Service.
Dependencies
jQuery
XML Objectifier
jQuery Soap Client (depends on jQuery and XML Objectifier)
var WS = function (url, ns, nsName) {
return function (method, parameters, callback) {
var i, j, para, soapBody = new SOAPObject(method), sr, response;
soapBody.ns = {
name: nsName,
uri: ns
};
if (typeof parameters === "function") {
callback = parameters;
} else if (parameters && parameters.length) {
for (i = 0, j = parameters.length; i < j; ++i) {
para = parameters[i];
soapBody.appendChild(new SOAPObject(para.name)).val(para.value);
}
}
sr = new SOAPRequest(method, soapBody);
SOAPClient.Proxy = url;
SOAPClient.SendRequest(sr, function (r) {
response = r.Body[0][method + "Response"][0]["return"][0]["Text"];
if (callback) {
callback.call(sr, response);
}
});
}
};
Usage
var ws = WS("http://127.0.0.1:8080/IM/TestService", "http://wservices/", "ns2");
ws("foo", [{name: "name", value:"dreas"}], function (r) {
console.log(r);
});
Disclaimer: This is still very much untested, so it can still blow up your computer