OTRS Webservice as Requestor Test - web-services

I'm new to OTRS (3.2) and also new to PERL but I have been given the task of setting up OTRS so that it will make a call to our remote webservice so a record can be created on our end when a ticket is set as "Closed".
I set up various dynamic fields so the customer service rep can fill in additional data that will be passed into the webservice call along with ticket details.
I couldn't get the webservice call to trigger when the ticket was "Closed" but I did get it to trigger when the "priority" was changed so I'm just using that now to test the webservice.
I'm just using the Test.pm and TestSimple.pm files that were included with OTRS.
When I look at the Debugger for the Webserice, I can see that the calls were being made:
$VAR1 = {
'TicketID' => '6'
};
My webservice currently just has one method "create" which just returns true for testing.
however I get the following from the Test.pm
"Got no TicketNumber (2014-09-02 09:20:42, error)"
and the following from the TestSimple.pm
"Error in SOAP call: 404 Not Found at /TARGET/SHARE/var/otrs/Kernel/GenericInterface/Transport/HTTP/SOAP.pm line 578 (2014-09-02 09:20:43, error)
I've spent countless hours on Google but couldn't find anything on this. All I could find is code for the Test.pm and TestSimple.pm but nothing really helpful to help me create a custom invoker for my needs and configure the webservice in OTRS to get it to work.
Does anyone have any sample invokers that I can look at to see how to set it up?
Basically I need to pass the ticket information along with my custom dynamic fields to my webservice. From there I can create the record on my end and do whatever processing.
I'm not sure how to setup the Invoker to pass the necessary ticket fields and dynamic fields and how to make it call a specific method in my remote webservice.
I guess getting the Test.pm and TestSimple.pm to work is the first step then I can modify those for my needs. I have not used PERL at all so any help is greatly appreciated.

I'm also struggling with similar set of requirements too. I've also never programmed in PERL, but I can tell you at least that the "Got no TicketNumber" in the Test.pm is right from the PrepareRequest method, there you can see this block of code:
# we need a TicketNumber
if ( !IsStringWithData( $Param{Data}->{TicketNumber} ) ) {
return $Self->{DebuggerObject}->Error( Summary => 'Got no TicketNumber' );
}
You should change all references to TicketNumber to TicketID, or remove the validation whatsoever (also there is mapping to ReturnedData variable).
Invoking specific methods on your WS interface is quite simple (but poorly documented). The Invoker name that you specify in the "OTRS as requester" section of web service configuration corresponds to the WS method that will be called. So if you have WS interface with a method called "create" just name the Invoker "create" too.
As far as the gathering of dynamic field goes, can't help you on that one yet, sorry.
Cheers

Related

How to specify the database in an ArangoDb AQL query?

If have multiple databases defined on a particular ArangoDB server, how do I specify the database I'd like an AQL query to run against?
Running the query through the REST endpoint that includes the db name (substituted into [DBNAME] below) ie:
/_db/[DBNAME]/_api/cursor
doesn't seem to work. The error message says 'unknown path /_db/[DBNAME]/_api/cursor'
Is this something I have to specify in the query itself?
Also: The query I'm trying to run is:
FOR col in COLLECTIONS() RETURN col.name
Fwiw, I haven't found a way to set the "current" database through the REST API. Also, I'm accessing the REST API from C++ using fuerte.
Tom Regner deserves primary credit here for prompting the enquiry that produced this answer. I am posting my findings here as an answer to help others who might run into this.
I don't know if this is a fuerte bug, shortcoming or just an api caveat that wasn't clear to me... BUT...
In order for the '/_db/[DBNAME/' prefix in an endpoint (eg full endpoint '/_db/[DBNAME/_api/cursor') to be registered and used in the header of a ::arangodb::fuerte::Request, it is NOT sufficient (as of arangodb 3.5.3 and the fuerte version available at the time of this answer) to simply call:
std::unique_ptr<fuerte::Request> request;
const char *endpoint = "/_db/[DBNAME/_api/cursor";
request = fuerte::createRequest(fuerte::RestVerb::Post,endpoint);
// and adding any arguments to the request using a VPackBuilder...
// in this case the query (omitted)
To have the database name included as part of such a request, you must additionally call the following:
request->header.parseArangoPath(endpoint);
Failure to do so seems to result in an error about an 'unknown path'.
Note 1: Simply setting the database member variable, ie
request->header.database = "[DBNAME]";
does not work.
Note 2: that operations without the leading '/_db/[DBNAME]/' prefix, seem to work fine using the 'current' database. (which at least for me, seems to be stuck at '_system' since as far as I can tell, there doesn't seem to be an endpoint to change this via the HTTP REST Api.)
The docs aren't very helpful right now, so just incase someone is looking for a more complete example, then please consider the following code.
EventLoopService eventLoopService;
// adjust the connection for your environment!
std::shared_ptr<Connection> conn = ConnectionBuilder().endpoint("http://localhost:8529")
.authenticationType(AuthenticationType::Basic)
.user(?) // enter a user with access
.password(?) // enter the password
.connect(eventLoopService);
// create the request
std::unique_ptr<Request> request = createRequest(RestVerb::Post, ContentType::VPack);
// enter the database name (ensure the user has access)
request->header.database = ?;
// API endpoint to submit AQL queries
request->header.path = "/_api/cursor";
// Create a payload to be submitted to the API endpoint
VPackBuilder builder;
builder.openObject();
// here is your query
builder.add("query", VPackValue("for col in collections() return col.name"));
builder.close();
// add the payload to the request
request->addVPack(builder.slice());
// send the request (blocking)
std::unique_ptr<Response> response = conn->sendRequest(std::move(request));
// check the response code - it should be 201
unsigned int statusCode = response->statusCode();
// slice has the response data
VPackSlice slice = response->slices().front();
std::cout << slice.get("result").toJson() << std::endl;

Not getting proper value in Camunda BPM when using queryProcessInstancesCount method call

http://localhost:8080/myApp/camunda-rest/engine/default/history/process-instance/count?processInstanceBusinessKey=myApp-201010
{
"count": 1
}
If I try to get from REST client it is providing me proper output(if the value exist in database). But I need to get the value from Java application using the below code,
ProcessInstanceRestService pIRS=new ProcessInstanceRestService("default");
ProcessInstanceQueryDto queryParameter=new ProcessInstanceQueryDto();
List<VariableQueryParameterDto> variables=new ArrayList<VariableQueryParameterDto>();
VariableQueryParameterDto variableQueryParameterDto = new VariableQueryParameterDto();
variableQueryParameterDto.setName("processInstanceBusinessKey");//processInstanceBusinessKey
variableQueryParameterDto.setValue("myApp-201010");
variables.add(variableQueryParameterDto);
queryParameter.setVariables(variables);
queryParameter.setParameter("myApp-201010");
CountResultDto cRD=pIRS.queryProcessInstancesCount(queryParameter);
return ""+cRD.getCount();
I am getting count as 0 everytime , Please let me know where I am going wrong
The business key is not a process variable. Also in the REST URL you query for historic process instances but in the code snipped you use the runtime process instance query. There are setter methods for the business key on both runtime (ProcessInstanceQueryDto#setBusinessKey) and history (HistoricProcessInstanceQueryDto#setProcessInstanceBusinessKey) DTOs.

Microsoft Dynamics CRM - Pass Parameters from Web Service to IPlugins

We are building some plugins in Microsoft Dynamics CRM by inheriting from IPlugin. We have these configured so they fire whenever an Account is updated.
The problem is the plugins are calling our services, which causes our service to respond with an update. We are doing some pretty hacky things right now to prevent these cyclical updates from happening.
We were wondering if there was a way to pass a value to the IOrganizationService service (the web service) that a plugin can look at. Our other system could send a flag ("hey, don't bothing sending an update!") and the plugin could skip calling back.
Can we pass parameters from web service to the plugins?
Good idea could be usage of custom flag-field. For example you add bit field and call it CallFromExternalSystem. So when you make an update from your external system through IOranizationService you just fill this flag with true field and in plugin you can check condition that this field is present in fields list so you have no need to call external system endpoint again.
We decided the correct solution was to use the value found in IPluginExecutionContext.InputParameters["Target"]. In the case of an Update, this returns an Entity containing attributes for all the attributes that were updated.
We basically have a list of attribute names we cared about. We loop through names and see if any of them appear in the entity attribute list. If so, we send an update to our other system. The good news is, Dynamics CRM ignores updates where the values don't actually change, so trying to update a value to itself is no-op.
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext));
Entity entity = (Entity)context.InputParameters["Target"];
string[] fields = new string[] { "name", "statecode", "address1_line1" };
bool hasUpdates = fields.Where(f => entity.Attributes.Contains(f)).Any();
if (!hasUpdates)
{
return;
}
}

How to call Soap\WSDL Service through a login required webpage using matlab?

I am new to the wsdl\soapmessage query\reply world( if i can put it in this way), and I am facing some difficulties using the following wsdl( which I really really hope, one will be so kind to look at at least one of the services described there)
http://almdemo.polarion.com/polarion/ws/services/TrackerWebService?wsdl
which was provided to me to develop a matlab webinterface. Right now my matlab code looks like this:
targetNamespace = 'http://ws.polarion.com/TrackerWebService';
method = 'queryWorkItems';
values= {'Query','Sort'}
names = {'query', 'sort'}
types ={'xsd:string','xsd:string'}
message = createSoapMessage( targetNamespace, method, values, names, types)
response = callSoapService('http://almdemo.polarion.com/polarion/ws/services',...
% Service's endpoint
'http://almdemo.polarion.com/polarion/#/workitems',...
% Server method to run
message)
% SOAP message created using createSoapMessage
author = parseSoapResponse(response)
Herewith to save you time I will just enonce my two problems:
Is the code correct?
Could someone tell me if such a wsdl link is just a definition of webservices or it is also a service's endpoint?
Normally to execute manually\per clicks this services on the weppage
http://almdemo.polarion.com/polarion, you have to login!
So how do I send a message in matlab which first log me in? Or must such a service be introduced into that wsdl for me to do it?? Could you be kind enough to write how it must be defined, because I don't really
write wsdl files, but I shall learn!**
I will be really thankful for your help and I wish you a happy week(-end) guys(& girls)!!!
Regards
Chrysmac
ps: I tried to use Soapui and gave that webpage as endpoint, but the toool crashes each time I enter my credentials! Maybe because of the dataload!??

Retrieve service information from WFS GetCapabilities request with GeoExt

This is probably a very simple question but I just can't seem to figure it out.
I am writing a Javascript app to retrieve layer information from a WFS server using a GetCapabilities request using GeoExt. GetCapabilities returns information about the WFS server -- the server's name, who runs it, etc., in addition to information on the data layers it has on offer.
My basic code looks like this:
var store = new GeoExt.data.WFSCapabilitiesStore({ url: serverURL });
store.on('load', successFunction);
store.on('exception', failureFunction);
store.load();
This works as expected, and when the loading completes, successFunction is called.
successFunction looks like this:
successFunction = function(dataProxy, records, options) {
doSomeStuff();
}
dataProxy is a Ext.data.DataProxy object, records is a list of records, one for each layer on the WFS server, and options is empty.
And here is where I'm stuck: In this function, I can get access to all the layer information regarding data offered by the server. But I also want to extract the server information that is contained in the XML fetched during the store.load() (see below). But I can't figure out how to get it out of the dataProxy object, where I'm sure it must be squirreled away.
Any ideas?
The fields I want are contained in this snippet:
<ows:ServiceIdentification>
<ows:Title>G_WIS_testIvago</ows:Title>
<ows:Abstract/>
<ows:Keywords>
<ows:Keyword/>
</ows:Keywords>
<ows:ServiceType>WFS</ows:ServiceType>
<ows:ServiceTypeVersion>1.1.0</ows:ServiceTypeVersion>
<ows:Fees/>
<ows:AccessConstraints/>
Apparently,GeoExt currently discards the server information, undermining the entire premise of my question.
Here is a code snippet that can be used to tell GeoExt to grab it. I did not write this code, but have tested it, and found it works well for me:
https://github.com/opengeo/gxp/blob/master/src/script/plugins/WMSSource.js#L37