I'm using nodejs and node-soap as client to consume a webservice published on iis and developed in delphi. The webservice is published with document/literal style.
On Node I'm invoking and logging the response of the operations like this:
client[functionName](args, function (err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
Here is a portion of the xml result from delphi:
...
<GetValuesResponse xmlns="urn:WS_TEST">
<res xmlns="urn:UTest">
<matrixData>
<TDoubleDynArray>
<double>4.32427893698308</double>
<double>4.40404718921869</double>
<double>4.50060875771443</double>
<double>4.56778202275494</double>
<double>4.61816197153533</double>
<double>4.73991351442126</double>
<double>4.78609513413661</double>
<double>4.8238800957219</double>
<double>4.8238800957219</double>
<double>4.81128510852681</double>
...
And this is the json obtained from node-soap (response):
...
"matrixData": {
"TDoubleDynArray": [
{
"double": [
"4.32427893698308",
"4.40404718921869",
"4.50060875771443",
"4.56778202275494",
"4.61816197153533",
"4.73991351442126",
"4.78609513413661",
"4.8238800957219",
"4.8238800957219",
"4.81128510852681",
...
I dont understand why node-soap includes the types of the data in the structure of the resulting json. Also, I don`t understand why arrays are parsed to json like an object with an array inside, instead of just an array.
Is there any way to ask node-soap just to include the data and the arrays just like simple arrays?
Here is the wsdl portion with the defines involved:
<element name="matrixData" type="ns6:TMatOfDouble"/>
<complexType name="TMatOfDouble">
<complexContent>
<restriction base="soapenc:Array">
<sequence/>
<attribute ref="soapenc:arrayType" n1:arrayType="ns1:TDoubleDynArray[]"/>
</restriction>
</complexContent>
</complexType>
<complexType name="TDoubleDynArray">
<complexContent>
<restriction base="soapenc:Array">
<sequence/>
<attribute ref="soapenc:arrayType" n1:arrayType="xs:double[]"/>
</restriction>
</complexContent>
</complexType>
Thanks in advance for any help
It result to be a bug in the node-soap library so we are trying to fix it.
Related
I need to add phone number to the registration page and need to save it in the db as well. I followed following link.
http://www.jhipster.tech/tips/022_tip_registering_user_with_additional_information.html
But since here Jhispter version is changed code is bit different than the code in above link. So I am bit confusing to go with it. According to the link instructions I did upto "Updating ManagedUserVM". Then after I need the help since code is differed.
It really didn't change that much, and the logic remains the same.
The registerAccount function should look like this now :
public void registerAccount(#Valid #RequestBody ManagedUserVM managedUserVM) {
if (!checkPasswordLength(managedUserVM.getPassword())) {
throw new InvalidPasswordException();
}
userRepository.findOneByLogin(managedUserVM.getLogin().toLowerCase()).ifPresent(u -> {throw new LoginAlreadyUsedException();});
userRepository.findOneByEmailIgnoreCase(managedUserVM.getEmail()).ifPresent(u -> {throw new EmailAlreadyUsedException();});
User user = userService.registerUser(managedUserVM, managedUserVM.getPassword(), managedUserVM.getPhone());
mailService.sendActivationEmail(user);
}
And the registerUser function in the UserService (which is a rename of the former createUser) :
public User registerUser(UserDTO userDTO, String password, String phone) {
// JHipster code omitted for brevity
...
// Create and save the UserExtra entity
UserExtra newUserExtra = new UserExtra();
newUserExtra.setUser(newUser);
newUserExtra.setPhone(phone);
userExtraRepository.save(newUserExtra);
log.debug("Created Information for UserExtra: {}", newUserExtra);
return newUser;
}
Just note that you may have to manually change your database changelog (if using a SQL database) to correctly link the ids of User and UserExtra, so it looks like this :
<createTable tableName="user_extra">
<column name="phone" type="varchar(255)">
<constraints nullable="true" />
</column>
<column name="user_id" type="bigint">
<constraints primaryKey="true" nullable="false" />
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
</createTable>
currently I'm building an application based on a legacy database.
Within this Database there are UserClasses e.g.:
UserclassEntity:
id
classname
parent
UserclassEntity
so I have rewritten the core service and added my custom voter to security.voter:
security.role_hierarchy:
class: AppBundle\Security\Role\RoleHierarchy
arguments:
- '%security.role_hierarchy.roles%'
- '#app.user_class_repository'
security.access.admin_voter:
class: AppBundle\Security\Voter\AdminVoter
arguments: ['#security.role_hierarchy']
tags:
- { name: security.voter, priority: 400 }
public: false
So I implemented all needed MEthods based on Original RoleHierarchy Class:
class RoleHierarchy extends orig_RoleHierarchy
{
/**
* #var array
*/
private $hierarchy;
/**
* #var UserclassRepository
*/
private $userClassRepository;
/**
* #var RoleManager
*/
private $manager;
/**
* #var UserclassRepository
*/
private $userclassRepository;
/**
* #param UserclassRepository $userclassRepository
* #param array $hierarchy
*/
public function __construct(UserclassRepository $userclassRepository, array $hierarchy)
{
$this->hierarchy = $hierarchy;
$this->userclassRepository = $userclassRepository;
$map = $this->buildRolesTree($this->hierarchy);
parent::__construct($map);
}
/**
* Here we build an array with roles. It looks like a two-levelled tree - just
* like original Symfony roles are stored in security.yml
*
* #param array $hierarchy
*
* #return array
*/
private function buildRolesTree(array $hierarchy = [])
{
$userclasses = $this->userclassRepository->findAll();
foreach ($userclasses as $userclass) {
/** #var $userclass Userclass */
if ($userclass->getParent()) {
if (!isset($hierarchy['ROLE_' . $userclass->getName()])) {
$hierarchy['ROLE_' . $userclass->getName()] = array();
}
$hierarchy['ROLE_' . $userclass->getName()][] = 'ROLE_' . $userclass->getParent()->getName();
} else {
if (!isset($hierarchy['ROLE_' . $userclass->getName()])) {
$hierarchy['ROLE_' . $userclass->getName()] = array();
}
}
}
return $hierarchy;
}
}
But when i clear the cache for prod environment i get an error:
[Symfony\Component\Debug\Exception\FatalErrorException]
Compile Error: require(): Failed opening required 'E:\projects\sf2\app\var\cache\pro_/doctrine/orm/Proxies\__CG__AppBundleEntityUserclass.php' (include_path='.;C:\php\pear')
This Exception throws because of missing Proxy Class, but I really don't know how to do this in another way. I need this Entity and I need the Role_Hierarchy based on this Entity.
Any Suggestions in how to fix this?
As suggested some more files:
doctrine's part of config.yml
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: LATIN1
mapping_types:
enum: string
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
dql:
string_functions:
COLLATE: AppBundle\DQL\CollateFunction
Doctrine ORM:
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="AppBundle\Entity\Userclass" table="userclass" repository-class="AppBundle\Repository\UserclassRepository">
<indexes>
<index name="name" columns="name,classname,class,color"/>
</indexes>
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="name" type="string" column="name" length="50" nullable="false">
<options>
<option name="fixed"/>
</options>
</field>
<field name="classname" type="string" column="classname" length="50" nullable="false">
<options>
<option name="fixed"/>
</options>
</field>
<field name="class" type="integer" column="class" nullable="false">
<options>
<option name="unsigned"/>
</options>
</field>
<field name="color" type="string" column="color" length="10" nullable="false">
<options>
<option name="fixed"/>
</options>
</field>
<many-to-one field="parent" target-entity="AppBundle\Entity\Userclass">
<join-column name="parent_id" referenced-column-name="id" />
</many-to-one>
</entity>
</doctrine-mapping>
I tried a lot of things but nothing really worked. As I found out, the proxy generate Task from doctrine:orm was removed in latest VErsion compatible with Symfony 3.1.x.
If someone struggle into this, the best way (I could find) was to set the
auto_generate_proxy_classes from "%kernel.debug%" to true
orm:
auto_generate_proxy_classes: "%kernel.debug%"
As simple as hell, only in dev environment this parameter is true. Running the application in productive mode, turns this obviosly to false, so Proxyclasses are not generated as they are needed. The Role Hierarchy is somehow triggered before doctrine got a chance to generate those needed proxies.
By enabling this auto_generate-option those proxies are generated as they were needed, and also cached. So any minimal performance break will only happen once. After generation these classes als also cached.
On my application I was not able to find any relevant or even little performance issues.
I'm using Spring Integration to parse XML file and i will need to create a thread (and each one have a different rate) for each tag.
Right now (with the help of many users here :)) i'm able to split XML by tag and then route it to the appropiate service-activator.
This works great but i'm not able to redirect to a channel that create "a thread" and then execute the operations. Right now i have the following configuration and in my mind (that i dont know if it is correct...)
Split tag -> Route to the appropiate channel -> Start a thread(from tag configuration) -> Execute the operation
This is my actual configuration that split tag and redirect to the channel.
The router should redirect not toward a channel directly, but schedule them.
In first instance will be enought to redirect it in a pool with fixed rate and later i will use XPATH to get the attribute and then replace this "fixed" rate with the correct value.
I've tried many solutions to create this flow but each one fails or do not compile :(
<context:component-scan base-package="it.mypkg" />
<si:channel id="rootChannel" />
<si-xml:xpath-splitter id="mySplitter" input-channel="rootChannel" output-channel="routerChannel" create-documents="true">
<si-xml:xpath-expression expression="//service" />
</si-xml:xpath-splitter>
<si-xml:xpath-router id="router" input-channel="routerChannel" evaluate-as-string="true">
<si-xml:xpath-expression expression="concat(name(./node()), 'Channel')" />
</si-xml:xpath-router>
<si:service-activator input-channel="serviceChannel" output-channel="endChannel">
<bean class="it.mypkg.Service" />
</si:service-activator>
UPDATE:
Using this configuration for the service this should run a task every 10 seconds (the id=service1) and every 5 seconds the other (the id=service2). In the same way i can have another tag that is handle by another class (because this will have another behaviour)
<root>
<service id="service1" interval="10000" />
<service id="service2" interval="5000" />
<activity id="activity1" interval="50000" />
<root>
I will have a classe (Service) that is general to handle Service tag and this complete some operation and then "return me" the value so i can redirect to another channel.
public class Service {
public int execute() {
// Execute the task and return the value to continue the "chain"
}
}
It's not at all clear what you mean; you split a tag; route it but want to "schedule" it at a rate in the XML. It's not clear what you mean by "schedule" here - normally each message is processed once not multiple times on a schedule.
As I said, I don't understand what you need to do, but a smart poller might be suitable.
Another possibility is the delayer where the amount of the delay can be derived from the message.
EDIT
Since your "services" don't seem to take any input data, it looks like you simply need to configure/start an <inbound-channel-adapter/> for each service, and then start it, based on the arguments in the XML.
<int:inbound-channel-adapter id="service1" channel="foo"
auto-startup="false"
ref="service1Bean" method="execute">
<poller fixed-delay="1000" />
</int:inbound-channel-adapter/>
Note auto-startup="false".
Now, in the code that receives the split
#Autowired
SourcePollingChannelAdapter service1;
...
public void startService1(Node node) {
...
service1.setTrigger(new PeridicTrigger(...));
service1.start();
...
}
I dont know if this is the right way to implement the flow, but i've write the follow code:
applicationContext.xml
<context:component-scan base-package="it.mypkg" />
<!-- Expression to extract interval from XML tag -->
<si-xml:xpath-expression id="selectIntervalXpath" expression="//*/#interval" />
<si:channel id="rootChannel" />
<!-- Split each tag to redirect on router -->
<si-xml:xpath-splitter id="mySplitter" input-channel="rootChannel" output-channel="routerChannel" create-documents="true">
<si-xml:xpath-expression expression="//service|//activity" />
</si-xml:xpath-splitter>
<!-- Route each tag to the appropiate channel -->
<si-xml:xpath-router id="router" input-channel="routerChannel" evaluate-as-string="true">
<si-xml:xpath-expression expression="concat(name(./node()), 'Channel')" />
</si-xml:xpath-router>
<!-- Activator for Service Tag -->
<si:service-activator input-channel="serviceChannel" method="schedule">
<bean class="it.mypkg.Service" />
</si:service-activator>
<!-- Activator for Activity Tag -->
<si:service-activator input-channel="activityChannel" method="schedule">
<bean class="it.mypkg.Activity" />
</si:service-activator>
<!-- Task scheduler -->
<task:scheduler id="taskScheduler" pool-size="10"/>
Each tag will extend an Operation class (to avoid code duplication on bean injection)
Operation.java
public abstract class Operation {
protected TaskScheduler taskScheduler;
protected XPathExpression selectIntervalXpath;
abstract public void schedule(Node document);
#Autowired
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler= taskScheduler;
}
public TaskScheduler getTaskScheduler() {
return this.taskScheduler;
}
#Autowired
public void setSelectIntervalXpath(XPathExpression selectIntervalXpath) {
this.selectIntervalXpath = selectIntervalXpath;
}
public XPathExpression getSelectIntervalXPath() {
return this.selectIntervalXpath;
}
}
And an example of Service class (that handle all tags service provided on .xml)
public class Service extends Operation {
private static final Logger log = Logger.getLogger(Service.class);
#Override
public void schedule(Node document) {
log.debug("Scheduling Service");
long interval = Long.parseLong(this.selectIntervalXpath.evaluateAsString(document));
this.taskScheduler.scheduleAtFixedRate(new ServiceRunner(), interval);
}
private class ServiceRunner implements Runnable {
public void run() {
log.debug("Running...");
}
}
}
Now to continue my flow i will need to find a way to redirect the output of each job to Spring Integration (applicationContext.xml).
i have a requirement to include authentication stuff on the <soap:Header> under a certain attribute name "RequestHeader" like <soap:Header><RequestHeader></RequestHeader></soap:Header><soap:Body>
but unfortunately, node-soap places this inside <soap:Body> instead.
so what i see is <soap:Header></soap:Header><soap:Body><RequestHeader>
question is, how do i move it to soap:Header? the wsdl might be at fault here but fixing it is not an option for now.
looking at the wsdl angle,
these are snippets from the wsdl, it's quite clear that the wsdl states that RequestHeaderElement should be in header, i wonder why it's being thrown to the body?
<wsdl:input name="SendSms">
<soap:header message="tns:SendSms" part="Headers" use="literal" />
<soap:body parts="Parameters" use="literal" />
</wsdl:input>
<wsdl:message name="SendSms">
<wsdl:part element="ns1:RequestHeaderElement" name="Headers" />
<wsdl:part element="tns:SendSmsRequestElement" name="Parameters" />
</wsdl:message>
Have you tried adding a XML string literal to the header?
const auth = '<RequestHeader></RequestHeader>'
soap.createClient(url, soapOptions, function (err, client) {
client.addSoapHeader(auth);
client.myFunction(args, function (err, result) {
console.log(client.lastRequest) //see the xml generated
});
});
Hi I am trying to fetch the accounts from CRM 2011. I am fetching the data in the EntityCollection . But when I am trying to read or access data from entityCollection it displayed first record but throwing an error after that record. Kindly have a look to below code and suggest me.
string fetch2 = #"
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
<entity name='account'>
<attribute name='name' />
<attribute name='address1_city' />
<attribute name='primarycontactid' />
<attribute name='telephone1' />
<attribute name='accountid' />
<order attribute='name' descending='false' />
<filter type='and'>
<condition attribute='accounttype' operator='eq' value='01' />
</filter>
</entity>
</fetch>";
try
{
EntityCollection fxResult = _service.RetrieveMultiple(new FetchExpression(fetch2));
foreach (var e in fxResult.Entities)
{
Console.WriteLine("Id:{0},Name:{1},City:{2}", e.Attributes ["accountid"].ToString(), e.Attributes["name"].ToString(), e.Attributes["address1_city"].ToString());
// Console.WriteLine("Id:{0},Name:{1},City:{2}", e.ToEntity["accountid"]);
}
}
catch (Exception e)
{
Console.WriteLine("Error:==" + e.Message);
}
Before access an attribute you need to ask if it is in the context:
e.Attributes.Contains("address1_city")
If the collection contains the attribute, then you can access it safe.
string accountid = (string)e.Attributes["address1_city"]
The reason the attribute doesn't come in the collection it's because it is null or you are not retrieving it. In this case maybe, one of your attributes is null. Maybe address1_city.
When retrieving attribute values of late-bound Entity objects, the recommended approach is to use method getAttributeValue<T>. When the attribute is not present in the entity's attribute collection, it returns default(T).
The primary key ('id') of the record is always present when it is returned by the OrganizationService.
So your code should look like this:
EntityCollection fxResult = _service.RetrieveMultiple(new FetchExpression(fetch2));
foreach (var e in fxResult.Entities)
{
Console.WriteLine(
"Id:{0},Name:{1},City:{2}",
e.Id,
e.GetAttributeValue<string>("name"),
e.GetAttributeValue<string>("address1_city"));
}
You can safely use the item selector when you need to assign a value to an attribute, regardless if it is already present or not.
E.g. the following code line is valid:
e["name"] = "Demo Accountname";