Integrate AngularJS App with SoftwareAG webMethods Integration Server - rest

I have been trying to set up a sample AngularJS app with webMethods Integration Server on the backend. Using $resource, I can easily pull normal JSON files and manipulate the data within the file. However, the goal is that I want to create services in webMethods Designer and call them from AngularJS using $resource to display the data in my app. The problem is that from AngularJS I cannot extract the data I need from the service that I'm creating in Designer. In Designer I can use (in WMPublic) documentToJSONString, and output something like:
jsonString {"id":"1", "name":"Dan", "quantity":"3"}
But I cannot extract the data because this is not a pure JSON string. Does anyone know how to (1) extract the JSON string output data using AnularJS or (2) output a JSON document from Designer? I am calling a REST service; something to the effect of
http://localhost:2222/rest/Get/getOrderData
from my services.js file in AngularJS.
Here is my services.js file:
/* Services */
var orderServices = angular.module('orderServices', ['ngResource']);
orderServices.factory('Order', ['$resource',
function($resource){
return $resource('http://localhost:2222/rest/REST/getOrderData', {}, {
query: {method:'GET', isArray:true}
});
}]);
Then, in my app, I want to use an ng-repeat to call things like {{order.id}}, {{order.name}} etc. Is anyone good with webMethods and Angular or done this before?

To force the response that you want, I would have used the service
pub.flow:setResponse mapping the jsonString to it's string parameter and probably hardcoded (eww!) the contentType parameter to 'application/json'
You may also need to use the service pub.flow:setResponseCode to set the response code.
They would be the last services in getOrderData
I would have invoked it using the below (where namespace is the folder structure in designer)
http://localhost:2222/invoke/namespace:getOrderData
The above applies to Integration Server V8 and it looks like you're using V9 since some of the services that you mention didn't exist in V8. This would also apply to a normal flow service, not a specific REST one (assuming they exist in V9).

Related

How to filter by dimension using Google Analytics Data API (GA4) Java client library?

I am trying to call Google Analytics Data API (GA4) using the Java client library and applying a dimension filter. This is the call which is working if I don't use the setDimensionFilter call:
RunReportRequest request =
RunReportRequest.newBuilder()
.setProperty(propertyId)
.addDimensions(com.google.analytics.data.v1beta.Dimension.newBuilder().setName("pageLocation"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("screenPageViews"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("activeUsers"))
// .setDimensionFilter(FilterExpression.newBuilder().setFilter(Filter.newBuilder().setStringFilter(
// Filter.StringFilter.newBuilder()
// .setMatchType(Filter.StringFilter.MatchType.FULL_REGEXP)
// .setField(Descriptors.FieldDescriptor, "pageLocation")
// .setValue("MY_REGEXP")
// .build())))
.addDateRanges(com.google.analytics.data.v1beta.DateRange.newBuilder()
.setStartDate(startDate.toStringYYYYMMDDWithDashes())
.setEndDate(endDate.toStringYYYYMMDDWithDashes()))
.setKeepEmptyRows(true)
.build();
I don't know how to use setDimensionFilter. If the usage which is commented in the previous code is correct, then the only thing missing is the call to setField. I don't know how to generate the Descriptors.FieldDescriptor instance (or even its meaning).
I have reviewed the client library javadoc, and also the code samples (which are really simple and unfortunately do not show any usage of setDimensionFilter).
The Descriptors.FieldDescriptor isn't part of the GA4 Data API and is an internal functionality of the protobuf framework
If you are trying to call this filter on a field with the name 'pageLocation' instead of using setField, I think you can do something like this
RunReportRequest request =
RunReportRequest.newBuilder()
.setProperty("properties/" + propertyId)
.addDimensions(com.google.analytics.data.v1beta.Dimension.newBuilder().setName("pageLocation"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("screenPageViews"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("activeUsers"))
.setDimensionFilter(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("pageLocation")
.setStringFilter(Filter.StringFilter.newBuilder()
.setMatchType(Filter.StringFilter.MatchType.FULL_REGEXP)
.setValue("MY_REGEXP"))))
.addDateRanges(com.google.analytics.data.v1beta.DateRange.newBuilder()
.setStartDate("2020-03-31")
.setEndDate("2021-03-31"))
.build();
Also, if you want an additional example of how to use setDimensionFilter, here is another code example that might help
RunReportRequest request =
RunReportRequest.newBuilder()
.setProperty("properties/" + propertyId)
.addDimensions(Dimension.newBuilder().setName("city"))
.addMetrics(Metric.newBuilder().setName("activeUsers"))
.addDateRanges(DateRange.newBuilder().setStartDate("2020-03-31").setEndDate("today"))
.setDimensionFilter(FilterExpression.newBuilder()
.setAndGroup(FilterExpressionList.newBuilder()
.addExpressions(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("platform")
.setStringFilter(Filter.StringFilter.newBuilder()
.setMatchType(Filter.StringFilter.MatchType.EXACT)
.setValue("Android"))))
.addExpressions(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("eventName")
.setStringFilter(Filter.StringFilter.newBuilder()
.setMatchType(Filter.StringFilter.MatchType.EXACT)
.setValue("in_app_purchase"))))))
.setMetricFilter(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("sessions")
.setNumericFilter(Filter.NumericFilter.newBuilder()
.setOperation(Filter.NumericFilter.Operation.GREATER_THAN)
.setValue(NumericValue.newBuilder()
.setInt64Value(1000)))))
.build();

How to wrap up external api response in order to meet json datasource backend requirements

I’m trying to create a grafana datasource plugin which is to return a response with table type format.
There is a third party rest API which should provide data to the datasource, however, the request/response format of this external API do not conform with the example simple-json-datasource plugin urls and requests formats.
Is there a way I could wrap up the external api response in the datasource backend methods (/query) which is then called by the front-end part of datasource? (external api URL will be provided at the datasource settings UI while adding the datasource)
I'll appreciate the answers/suggestion.
You would have to write code that transforms the third party API response into the table type format.
You may want to start off of something like this: https://github.com/grafana/simple-json-datasource
Clone that project, and change the url values passed in options to the doRequest() function, those values should point to your third party API.
The doRequest() function seems to return a Promise, so you can do your data transformation when they are fulfilled, for example:
// simple-json-datasource/src/datasource.js
// in the query() function
return this.doRequest(options).then(function(result) {
// your transform code here;
return transformedResult;
})

Spring WS remove flexible URL, Restricting WSDL URL and service URL

I'm trying to make a Spring Boot Soap WebService application, and was following the Get Started (https://spring.io/guides/gs/producing-web-service/) example to learn how to do this.
I've created what I want, but I have two URL problems with this setup and I could not find what configuration should I change to fix this :
WSDL URL basic is localhost:8080/ws/countries.wsdl but anything like localhost:8080/ws/whatever/countries.wsdl is correct
service URL for SoapUI request is localhost:8080/ws but anything like localhost:8080/ws/whatever is correct
I know that this is a feature for Spring WS, but I want a fixed URL (without 'whatever' in both cases) and could not find what to change for this
There is no straight forward way to restrict the way you want.
SOAP service is not URL based.
SOAP message body describe the endpoint.
The thing you wanted is possible following way.
Changing URL mapping in ServletRegistrationBean to restrict URL access
Existing /ws/* mapping is the reason why all the /ws/whatever url successfully responded.
Change as new ServletRegistrationBean(servlet, "/ws");
Effect will be you can not request other than /ws URL
Now the problem is, you can not get WSDL by this mapping.
Solution to get WSDL
The DefaultWsdl11Definition is actually generating WSDL from XSD on every request.
Save countries.wsdl to resource folder as static WSDL file.
Remove DefaultWsdl11Definition bean.
Create a new SimpleWsdl11Definition bean as like
#Bean(name = "countries")
public SimpleWsdl11Definition orders() {
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("countries.wsdl"));
return wsdl11Definition;
}
Now add another static URL mapping in ServletRegistrationBean. As it will be finally look like new ServletRegistrationBean(servlet, "/ws", "/ws/countries.wsdl");
This practice is good for development phase as you can publish easily the changed definition. But it is recommended to use static-wsdl for production environment. Details ** here
Just change
return new ServletRegistrationBean(servlet, "/ws/*");
for example to
return new ServletRegistrationBean(servlet, new String[]{
"/ws/v1/countries.wsdl",
"/ws/v2/countries.wsdl"
});

How do I customise the Ember store path for a specific model?

I have an API endpoint at /movies/:movie_id/actors.
I'm trying to use Ember Data to fetch this endpoint. I'm not interested in modelling movies at this point, just actors. My route looks like this:
this.route('actors', { path: '/movies/:movie_id/actors' });
My actor model is plain:
DS.Model.extend({
name: DS.attr("name")
})
In my actors route, I have:
model: function(params) {
// params contains movie_id
return this.store.findAll('actor')
}
This will cause Ember to send a request for /actors. How can I tell Ember to send a request to /movies/:movie_id/actors instead?
My JSON is being returned in the format { "movies": [ { … } ] } and I'm using the DS.ActiveModelAdapter, if that's at all relevant. I'm using Ember 2.0.
DS.Store doesn't work around "path" concept. It's more of a data bucket, which - when supplemented - can take burden of working with provider (fetch/update/create/cache etc.) off developer. In your case it looks similar to this:
ActiveModelAdapter, which you're using right now is using specific convention for accessing and isn't compatible with your data provider. So, what options do you have?
Customize ActiveModelAdapter by overriding pathForType or buildURL methods (note - links are for RESTAdapter, since ActiveModelAdapter subclasses it)
Choose more compatible adapter or even write your own
Don't use adapter - fetch the data through AJAX and feed it to store directly using push()/pushPayload()

HATEOAS client with AngularJS

I was wondering if there were any features hidden in Angular or exposed by some 3rd-party libraries to easily create HATEOAS-compliant Restful clients.
On backend side, I am using Spring Data/REST to produce an HATEOAS JSON API.
Consuming it, though, is quite another story.
For instance, I've got those 3 entities:
Company {name, address}
Employee {firstName, lastName, employer[Company]}
Activity {rate, day, employee[Employee], client[Company]}
and requesting an activity (the most complex entity of the model) produces something like this:
{
links: [],
content: [{
rate: 456,
day: 1366754400000,
links: [{
rel: "self",
href: "http://localhost:8080/api/activities/1"
},
{
rel: "activities.activity.client",
href: "http://localhost:8080/api/activities/1/client"
},
{
rel: "activities.activity.employee",
href: "http://localhost:8080/api/activities/1/employee"
}]
}]
}
My API talks in terms of REST (resources identified by links).
An Activity has an Employee for instance. What I really want to use is : {rate: 456, day: 1366754400000, employee: {firstName:"xxx", lastName:"xxx" ...}}.
However, as you can see in the first output, my Activity only contains a link to the employee, not its data. Is there anything in Angular or in a 3rd-party library to resolve those links and embed the resulting data instead?
Any input on this?
Thanks in advance!
Checkout angular-hateoas. ITs an AngularJS module for using $resource with a HATEOAS-enabled REST API.
You could write a Response Transformation that would inspect your returned object, check for links, and resolve them before returning the response. See the section "Transforming Requests and Responses" in the $http service documentation.
Something like this:
transformResponse: function(rawData) {
var json = JSON.parse( rawData );
forEach( json.content.links, function(link) {
// resolve link...
});
return json;
}
Since the "resolve link" step is itself an $http call, sub-references would also be resolved. HOWEVER, since these are asynchronous, you would likely return a promise instead of the real value; I don't know if the transform function is allowed to do this.
As #charlietfl pointed out, however, please note that this will result in several HTTP calls to return a single entity. Even though I like the concept of HATEOAS, this will likely result in sluggishness if too many calls are made. I'd suggest that your server return the data, or some of it, directly, PLUS the link for details.
Based on your comment about wanting to work with data as against links on the client, I think Restangular would be a good fit.
I've been using angular-hal for one of my projects. It was a Spring HATEOAS backend. And I didn't run into any issues. It handles parametrized resources. I suspect it only supports HAL so since you're using Spring Data Rest you probably have to configure it to generate HAL compliant responses.
I think the confusion may be that you are asking for an Angular solution, when what you really want to do is have Spring Data send a more complete JSON response. I.e, you really just want the server to return the employee data as part of the response JSON, rather than having the client perform extra steps to look it up. I don't know what data store you are using in Spring Data, but the general solution would be to add public getEmployee() method to your Activity class and then annotate the method with #RelatedTo and #Fetch (this would be the setup for Neo4J -- may be different annotations for your flavor of Spring Data). This should cause Spring HATEOAS to include the Employee record within the response for /activity. Hope this helps.