I had some problems configuring and connecting my ChromeCast with a mobile device. Everything worked fine with my laptop, but when I tried to cast from my tablet or phone my connection kept dropping.
I figured out that it had to do with my dual band router. My router (Asus RT-AC56u) supports 2.4 GHz and 5 GHz. When I disabled the 5 GHz, everything worked like a charm.
It seems that a ChromeCast only supports 2.4 GHz, so you have to be sure that your mobile device is connected through te same network.
It's also bad practice to name both your networks (2.4 and 5) the same, this can give connection errors like connections that are temporarily unavailable or a very low speeds.
Friday, February 6, 2015
Wednesday, August 6, 2014
Problems with WSDL files in Coldfusion 11 using XSD's or other external files
Another gotcha when using externals WSDL files in Coldfusion 11 webservices: you can not use relative references in the files, all references should be absolute:
Will not work anymore:
<xsd:include schemaLocation="somefile.xsd" />
Should be:
<xsd:include schemaLocation="http://www.somesite.com/somefile.xsd" />
Will not work anymore:
<xsd:include schemaLocation="somefile.xsd" />
Should be:
<xsd:include schemaLocation="http://www.somesite.com/somefile.xsd" />
Publishing webservices in ColdFusion 11 in old Axis version (webservice gives an error after upgrading coldfusion)
ColdFusion 11 has a new axis version. This means that webservices are now published in AXIS2. This should not give too much problems unless you have written the WSDLs yourself. The easiest fix is to tell Coldfusion that this is an older version by adding one element in the component object (or cfcomponent tag): wsversion = "1". That's it!
Tuesday, July 29, 2014
Unlocking a samsung phone or tablet / backing up without a working screen
I was having some problems with my Samsung tablet: the screen stopped working but everything else seemed to work. I could boot up the device, hear the startup sound, use the buttons, but could not see anything on the screen. It was time to send it in for repair, but before that I wanted to make a backup of my data. There is only one problem: Kies will not access the files if there is a screen lock! There was no way for me to type in my password without to be able to see what I am typing so I could not backup the data. Luckily, there is a solution: MySamsung. I created a MySamsung account when I installed my tablet which enables all sorts of extra features. One very usefull option: remote screen unlocking.
If you login on the samsung site there is a "find my mobile" option (or you can go to http://findmymobile.samsung.com/account/init.do ).
Select your device.
Choose remote screen unlock
Start the wizard.
If your device has an internet connection it will be contacted by the service and the screen lock will be removed. This may take a while but when it is succesfull you will see that Kies opens the device.
This worked for my Galaxy Note 10.1 2014 (SM-P600) and my Galaxy S4 (GT-I9505), but should work for any Samsung mobile device that has an internet connection.
So now the repair people can do anything they want with my broken device, when I get a completely data wiped device back I can now just restore my old data!
If you login on the samsung site there is a "find my mobile" option (or you can go to http://findmymobile.samsung.com/account/init.do ).
Select your device.
Choose remote screen unlock
Start the wizard.
If your device has an internet connection it will be contacted by the service and the screen lock will be removed. This may take a while but when it is succesfull you will see that Kies opens the device.
This worked for my Galaxy Note 10.1 2014 (SM-P600) and my Galaxy S4 (GT-I9505), but should work for any Samsung mobile device that has an internet connection.
So now the repair people can do anything they want with my broken device, when I get a completely data wiped device back I can now just restore my old data!
Friday, November 2, 2012
Initiating web service objects using class files
If you want to call a webservice which uses more complex arguments then it's easier (or even best practice) to use class files in stead of recreating the objects by yourself. Here is how:
- Open your ColdFusion9/stubs/ folder.
- Make a call to the webservice using createObject:
someWs = createObject("webservice", "http://addressToWsdlFile/?wsdl"); - Inspect the stubs folder and find the subfolder which is newly created, open it.
- There should be a whole subfolder structure which contains eventually some .class files. Copy the root (normaly this is something like a top level domain: com or net or such)
- Paste the folder structure to folder which is noted as a class path folder, or make a new folder and put this in the ColdFusion administrator (Server Settings > Java and JVM > ColdFusion Class Path) or in your server.cfc class path settings
- Restart ColdFusion (do not forget this!)
- Now you can create one of the objects needed in the webservice using:
someObject = createObject("java", "com.test.testapp.testObj);
(the dot notated path is corresponding with the copied folder structure to the class files) - The objects should have all the getters and setters. (Use writeDump() (or cfdump) to see all the properties of the classes). So use someObject.setSomeValue("xxx"); to populate.
- Call the method with the generated object:
result = someWs.someMethod(someObject); - Done!
Using SSL with ColdFusion howto
Here is a writeup about how to setup ColdFusion 9 to use SSL. I will describe the steps I needed to take to connect to a site that uses https.
Click on the button "copy to file" to export the certificate. Choose "Base-64 encoded X.509 (.CER) and choose the filename and location.
You have two keystore files: cacerts and trustStore, the cacerts should only contain the root certificates from the Certificate Authorities (CA) and the trustStore should contain the trusted certificates in which you should import the certificate of the server you wish to connect.
If you use the CFadmin plugin, open the KeystoreManager.cfc and set the KeyStorePath if it is not the default setting and the password (the default settings should be fine). In the init function you can change the file of the keystore which you specified in the jrun.xml in step 2.
If you use the keytool file, open a command prompt and go to the bin folder of your CF jre. There you can find the keytool.exe file.
Make a keystore named trustStore (if it does not exist) by generating a server certificate:
keytool -genkey -v -alias cf -dname "cn=localhost" -keystore trustStore -keypass changeit -storepass changeit
Alias (here set to "cf") is the short name for the certificate, trustStore is the name of the keystore (you should use an absolute path to be shure where the keystore file is written to, the keypass and storepass are the passwords to secure the certificate and the keystore (changeit is default, so it's advised to change this, but be shure it is the same as what is set in the jrun.xml file in step 2).
Import the certificate of the remote server to the trustStore:
keytool -import -v -alias savedCertAlias -file savedCert.cer -keystore trustStore
savedCertAlias is the short name of the to be imported certificate, savedCert.cer is the file of the certificate you saved in step 1 (use an absolute path to be sure you will import the right file), strustStore is the file of the keystore you will save the certificate to (use an absolute path). Consider the -trustcacerts option if you want to trust the whole tree.
List the contents of the keystore or truststore:
keytool -list -keystore keystorefile
-Xdebug -Djavax.net.debug=all
This will save all sorts of handy debug output to runtime\logs folder coldfusion-out which comes in handy to see how the SSL connection works (or not).
Jrun Help / Import certificates | Certificate stores | ColdFusion: http://helpx.adobe.com/coldfusion/kb/import-certificates-certificate-stores-coldfusion.html
Debugging SSL/TLS Connections: http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/ReadDebug.html
Search for SSL in: "Configuring and administering ColdFusion"
1: inspect the site and download the certificate
Go to the site and inspect the certificate. I use Google Chrome, so I clicked on the lock icon next to the address in the adress bar. Then click on the certificate details.Click on the button "copy to file" to export the certificate. Choose "Base-64 encoded X.509 (.CER) and choose the filename and location.
2: enable SSL in Jrun.xml
Open the Jrun.xml and search for "SSLService". Here you will see a commented section where all the setting about SSL are. Set the port to the right value (443 is the standard port for ssl), set the right location for keyStore and trustStore. My values are "{jrun.rootdir}/lib/security/cacerts" and "{jrun.rootdir}/lib/security/trustStore". Not sure where the jrun.rootdir points to? Look in the ColdFusion Administrator in "system information" > "Java Home".3: import the certificate
Here you'll have two options: use the gui in the ColdFusion administrator http://certman.riaforge.org/ (which is the easiest), or import the certificate using the JRE keytool.You have two keystore files: cacerts and trustStore, the cacerts should only contain the root certificates from the Certificate Authorities (CA) and the trustStore should contain the trusted certificates in which you should import the certificate of the server you wish to connect.
If you use the CFadmin plugin, open the KeystoreManager.cfc and set the KeyStorePath if it is not the default setting and the password (the default settings should be fine). In the init function you can change the file of the keystore which you specified in the jrun.xml in step 2.
If you use the keytool file, open a command prompt and go to the bin folder of your CF jre. There you can find the keytool.exe file.
Make a keystore named trustStore (if it does not exist) by generating a server certificate:
keytool -genkey -v -alias cf -dname "cn=localhost" -keystore trustStore -keypass changeit -storepass changeit
Alias (here set to "cf") is the short name for the certificate, trustStore is the name of the keystore (you should use an absolute path to be shure where the keystore file is written to, the keypass and storepass are the passwords to secure the certificate and the keystore (changeit is default, so it's advised to change this, but be shure it is the same as what is set in the jrun.xml file in step 2).
Import the certificate of the remote server to the trustStore:
keytool -import -v -alias savedCertAlias -file savedCert.cer -keystore trustStore
savedCertAlias is the short name of the to be imported certificate, savedCert.cer is the file of the certificate you saved in step 1 (use an absolute path to be sure you will import the right file), strustStore is the file of the keystore you will save the certificate to (use an absolute path). Consider the -trustcacerts option if you want to trust the whole tree.
List the contents of the keystore or truststore:
keytool -list -keystore keystorefile
4: Enable jvm debug output (optional)
This step is optional, but great to see if everything is working. Add the folowing line to the JVM arguments in the CF administrator:-Xdebug -Djavax.net.debug=all
This will save all sorts of handy debug output to runtime\logs folder coldfusion-out which comes in handy to see how the SSL connection works (or not).
5: Restart ColdFusion
For all the indivdual steps a restart of the ColdFusion instance is needed so this is a good moment to do so. (changed jvm.xml, added keys to keystore, changed jvm arguments).
6: Check the SSL connection
Make a call to the server which you want to connect to:
<cfhttp
url="https://someSSLEnabledServer/index.php?someargs=1"
charset="utf-8"
method="post"
port="443"
result="test" >
If you enabled jvm debug output (step 4) you can see the SSL connection results in the -out log file.
7: Debug!
If everything is working, congratulations! Be sure to disable the debugging because one ssl connection can generate a few Kb of logging information in one call.
If the call fails you should get some hints in the log file, do not trust the coldfusion exceptions you get in your browser, they are not detailed enough to see what is going on. Here are some pointers to what might go wrong:
Keystore or trustStore not found: be sure the files exist and the paths are correct in the jvm.xml. Change the paths and/or generate the keyStore
Not all the CA's of the certificate are trusted by the keystore: Open the imported certificate file and check the certification path. Check all the CA's in the certification path and be shure that all the certificates are either in the keystore or the trustStore. If not then import them to the trustStore (repeat the steps 1-3) and/or consider the -trustcacerts option (see keytool manual).
No CA's are in the trustStore: On one CF server I found a keyStore with only three CA records. You can import all the CA's, but it might be easier to see if your JRE has an updated file.
Certificate or one of the CA's are expired: check if all the certificates in the chain are still valid and updated in your keystores.
Note: This description assumes that only one way ssl signing is needed, if the SSL server requires a certificate from the client you should generate a valid certificate and import it in the keystore. The keytool is limited to X509 v1 generation.If you need X509 v3 then you should use openSSL or another capable tool. Use a tool that is capable of importing private keys, the keytool is not capable to do this.
Note: This description assumes that only one way ssl signing is needed, if the SSL server requires a certificate from the client you should generate a valid certificate and import it in the keystore. The keytool is limited to X509 v1 generation.If you need X509 v3 then you should use openSSL or another capable tool. Use a tool that is capable of importing private keys, the keytool is not capable to do this.
Here are some references I used:
Tool to import certificates: http://certman.riaforge.org/Jrun Help / Import certificates | Certificate stores | ColdFusion: http://helpx.adobe.com/coldfusion/kb/import-certificates-certificate-stores-coldfusion.html
Debugging SSL/TLS Connections: http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/ReadDebug.html
Search for SSL in: "Configuring and administering ColdFusion"
Wednesday, June 27, 2012
Weird thing in for loop in ColdFusion
I was making a simple XML iteration in script using a for loop, but it only returned one element in stead of all the elements. In a further inspection I discovered a typo which was not reported by ColdFusion.
Here is the for loop:
for (sCount=1; sCount<+arrayLen(xmlSomething["anotherElement"]); sCount++){
}
The problem is the <+ operator which should be <=
But no error report, just the first element that is returned. I wonder why!
Here is the for loop:
for (sCount=1; sCount<+arrayLen(xmlSomething["anotherElement"]); sCount++){
}
The problem is the <+ operator which should be <=
But no error report, just the first element that is returned. I wonder why!
Monday, June 18, 2012
Using different axis types in webservices (like unsigned int)
This is just a reminder for myself:
I read a great article about using the different datatypes that are not supported in ColdFusion (and not through JavaCast()). The way to go is to use the underlying axis object:
duration = CreateObject("java", "org.apache.axis.types.UnsignedInt").init(60);
In the example the variable "duration" is of type "UnsignedInt" and has the value 60. You can also do this in XML (see my previous post), but this is more elegant in my opinion.
I read a great article about using the different datatypes that are not supported in ColdFusion (and not through JavaCast()). The way to go is to use the underlying axis object:
duration = CreateObject("java", "org.apache.axis.types.UnsignedInt").init(60);
In the example the variable "duration" is of type "UnsignedInt" and has the value 60. You can also do this in XML (see my previous post), but this is more elegant in my opinion.
Friday, June 15, 2012
Question: how to throw an error in a ColdFusion web service?
I've been trying to solve this promblem for some time now, but it seems there is no simple solution for this:
When you look at your webservice WSDL you have three operation parts: input, output and fault. The fault type of a generated ColdFusion WSDL is "CFCInvocationException". This is fine for most purposes, but not in my case. For example: I want to validate the input of the web service call to see if everything is correct before executing the method. Let's say you have a service to order something, then you want to authenticate the user, check the amount, and see if the product is available. If something is not correct then I want to return a fault.
In the service you can set the HTTP status code to 500 by using getPageContext().getResponse().setstatus(500);
But I still want to return a fault code and a fault message. If I generate this and return it in the body it will be returned in the SOAP output part, and not in de fault part. If I use "throw" to return the error, then it will be added to the "CFCInvocationException" and not my own fault type.
throw (message="some",type="urn:errorType",errorCode="999");
Does anyone have a solution to return a valid custom web service error (that is defined in the service WSDL) that will not be overrided by the ColdFusion fault handler?
UPDATE:
I haven't yet looked into CF11 so I don't know if this is fixed in that version, but I read a solution which isn't very elegant, but works. In short: you have to give the webservices their own application.cfc and use the onError function to catch the ColdFusion generated exception and replace the content by soap XML. A sample is described here: http://laksmatee.blogspot.nl/2014/02/half-baked-soap-support-in-coldfusion-9.html
When you look at your webservice WSDL you have three operation parts: input, output and fault. The fault type of a generated ColdFusion WSDL is "CFCInvocationException". This is fine for most purposes, but not in my case. For example: I want to validate the input of the web service call to see if everything is correct before executing the method. Let's say you have a service to order something, then you want to authenticate the user, check the amount, and see if the product is available. If something is not correct then I want to return a fault.
In the service you can set the HTTP status code to 500 by using getPageContext().getResponse().setstatus(500);
But I still want to return a fault code and a fault message. If I generate this and return it in the body it will be returned in the SOAP output part, and not in de fault part. If I use "throw" to return the error, then it will be added to the "CFCInvocationException" and not my own fault type.
throw (message="some",type="urn:errorType",errorCode="999");
Does anyone have a solution to return a valid custom web service error (that is defined in the service WSDL) that will not be overrided by the ColdFusion fault handler?
UPDATE:
I haven't yet looked into CF11 so I don't know if this is fixed in that version, but I read a solution which isn't very elegant, but works. In short: you have to give the webservices their own application.cfc and use the onError function to catch the ColdFusion generated exception and replace the content by soap XML. A sample is described here: http://laksmatee.blogspot.nl/2014/02/half-baked-soap-support-in-coldfusion-9.html
Returning a complex object with specfic data types in a ColdFusion web service
Here is a folow-up on my previous post about returing an integer in a webservice. Most webservices return more then one value. In this example I will return a structure with a firstname and lastname:
<cfcomponent output="false">
<cffunction name="giveMeAPerson" output="false" access="remote" returnType="person">
<cfset var stReturn = createObject("component","person") />
<cfset stReturn.firstName = "John" />
<cfset stReturn.lastName = "Doe" />
<cfset stReturn.age = "30" />
<cfreturn stReturn />
</cffunction>
</cfcomponent>
The returnType="person" points to person.cfc which is a value object with three properties: firstName, lastName and age with the according data type (string and numeric). (If the person.cfc is in a different folder than the web service cfc, then you must use the dot delimited path in the returnType field.)
If you want to use a specific data type for every struct key you will have to use XML. If you want the web service consumers to be able to fully use the different data types you have to specify the data types in the WSDL file. Save the generated WSDL to a file and point to this file in your component (see my previous post for the details on this). Next, edit the WSDL where the returnType is specified. Here I will change the data type "double" of the property "age" to "int". Next I will set the returntype of the function "giveMeAPerson" to "any".
Now it is time to construct the XML that has to be returned:
var XmlResponse = XmlNew();
XmlResponse.xmlRoot = XmlElemNew(XmlResponse,"urn:pointerToURN","giveMeAPersonResponse");
XmlResponse.xmlRoot.XmlAttributes['xsi:type'] = "giveMeAPersonResponse";
XmlResponse.xmlRoot.XmlChildren[1] = XmlElemNew(XmlResponse,"urn:customUrn","firstName");
XmlResponse.xmlRoot.XmlChildren[2] = XmlElemNew(XmlResponse,"lastName");
XmlResponse.xmlRoot.XmlChildren[3] = XmlElemNew(XmlResponse,"age");
XmlResponse.xmlRoot.firstName.XmlAttributes['xsi:type'] = "firstname";
XmlResponse.xmlRoot.lastname.XmlAttributes['xsi:type'] = "xsi:string";
XmlResponse.xmlRoot.age.XmlAttributes['xsi:type'] = "xsi:int";
XmlResponse.xmlRoot. firstName .XmlText = "John";
XmlResponse.xmlRoot.lastname.XmlText = "Doe";
XmlResponse.xmlRoot.age = JavaCast("int",30);
Then return the XmlResponse.
Note: In this example I used a custom data type for firstName. I did this to show you what to change to implement this. The custom data type must be defined in the WSDL under the given URN.
The conversion to int and string is not necessary, if you describe the type in the WSDL then ColdFusion will do the conversion.
<cfcomponent output="false">
<cffunction name="giveMeAPerson" output="false" access="remote" returnType="person">
<cfset var stReturn = createObject("component","person") />
<cfset stReturn.firstName = "John" />
<cfset stReturn.lastName = "Doe" />
<cfset stReturn.age = "30" />
<cfreturn stReturn />
</cffunction>
</cfcomponent>
The returnType="person" points to person.cfc which is a value object with three properties: firstName, lastName and age with the according data type (string and numeric). (If the person.cfc is in a different folder than the web service cfc, then you must use the dot delimited path in the returnType field.)
If you want to use a specific data type for every struct key you will have to use XML. If you want the web service consumers to be able to fully use the different data types you have to specify the data types in the WSDL file. Save the generated WSDL to a file and point to this file in your component (see my previous post for the details on this). Next, edit the WSDL where the returnType is specified. Here I will change the data type "double" of the property "age" to "int". Next I will set the returntype of the function "giveMeAPerson" to "any".
Now it is time to construct the XML that has to be returned:
var XmlResponse = XmlNew();
XmlResponse.xmlRoot = XmlElemNew(XmlResponse,"urn:pointerToURN","giveMeAPersonResponse");
XmlResponse.xmlRoot.XmlAttributes['xsi:type'] = "giveMeAPersonResponse";
XmlResponse.xmlRoot.XmlChildren[1] = XmlElemNew(XmlResponse,"urn:customUrn","firstName");
XmlResponse.xmlRoot.XmlChildren[2] = XmlElemNew(XmlResponse,"lastName");
XmlResponse.xmlRoot.XmlChildren[3] = XmlElemNew(XmlResponse,"age");
XmlResponse.xmlRoot.firstName.XmlAttributes['xsi:type'] = "firstname";
XmlResponse.xmlRoot.lastname.XmlAttributes['xsi:type'] = "xsi:string";
XmlResponse.xmlRoot.age.XmlAttributes['xsi:type'] = "xsi:int";
XmlResponse.xmlRoot. firstName .XmlText = "John";
XmlResponse.xmlRoot.lastname.XmlText = "Doe";
XmlResponse.xmlRoot.age = JavaCast("int",30);
Then return the XmlResponse.
Note: In this example I used a custom data type for firstName. I did this to show you what to change to implement this. The custom data type must be defined in the WSDL under the given URN.
The conversion to int and string is not necessary, if you describe the type in the WSDL then ColdFusion will do the conversion.
Returning an integer (or other data types) with a ColdFusion web service
ColdFusion is a webserver language which is easy to learn and makes it easy to quickly achieve complex operations. This is all very nice, but can get in the way if you want to do something in a specific way. This problem arises when you have to deliver a webservice that returns a specific data type.
Here is a webservice which returns a number:
<cfcomponent output="false">
<cffunction name="giveMeANumber" output="false" access="remote" returnType="numeric">
<cfreturn RandRange(0,10) />
</cffunction>
</cfcomponent>
If you call the web service in a different language than ColdFusion, or in a specific web service tool (like SoapUI) you will see that the returned value will be something like "5.0". This will be no problem for ColdFusion, but this may come as a problem for PHP or .Net. That's why I want the service to return "5" in stead of "5.0".
If you look at the webservice WSDL you will see that the webservice returns a double:
Save the whole WSDL content to a text file and be sure that it is XML compliant (ie. no leading spaces before the XML tag). Now you can change the data type of the return value:
Next, change the component tag to use the external wsdlfile:
<cfcomponent wsdlfile="myExternalwsdlfile.wsdl" style="document" output="false">
If you point to an external WSDL file you have to set style="document".
Next, set the returntype of the function to "any", this is not required for int (double or int are both numeric), but it is best practice because it will be required for other data type.
<cffunction name="giveMeANumber" output="false" access="remote" returnType="any">
Next, use Javacast around the return value to set the right data type, in this case: <cfreturn JavaCast("int",RandRange(0,10)) />
To see which data type in ColdFusion will be returned with which data type (and if it may cause problems, see the ColdFusion reference "Data conversions between ColdFusion and WSDL data types".
Here is a webservice which returns a number:
<cfcomponent output="false">
<cffunction name="giveMeANumber" output="false" access="remote" returnType="numeric">
<cfreturn RandRange(0,10) />
</cffunction>
</cfcomponent>
If you call the web service in a different language than ColdFusion, or in a specific web service tool (like SoapUI) you will see that the returned value will be something like "5.0". This will be no problem for ColdFusion, but this may come as a problem for PHP or .Net. That's why I want the service to return "5" in stead of "5.0".
If you look at the webservice WSDL you will see that the webservice returns a double:
<wsdl:message name="giveMeANumberResponse">
<wsdl:part name="giveMeANumberReturn" type="xsd:double"/>
</wsdl:message>
Save the whole WSDL content to a text file and be sure that it is XML compliant (ie. no leading spaces before the XML tag). Now you can change the data type of the return value:
<wsdl:message name="giveMeANumberResponse">
<wsdl:part name="giveMeANumberReturn" type="xsd:int"/>
</wsdl:message>
Next, change the component tag to use the external wsdlfile:
<cfcomponent wsdlfile="myExternalwsdlfile.wsdl" style="document" output="false">
If you point to an external WSDL file you have to set style="document".
Next, set the returntype of the function to "any", this is not required for int (double or int are both numeric), but it is best practice because it will be required for other data type.
<cffunction name="giveMeANumber" output="false" access="remote" returnType="any">
Next, use Javacast around the return value to set the right data type, in this case: <cfreturn JavaCast("int",RandRange(0,10)) />
To see which data type in ColdFusion will be returned with which data type (and if it may cause problems, see the ColdFusion reference "Data conversions between ColdFusion and WSDL data types".
Wednesday, May 30, 2012
Coldfusion, SOAP headers and custom namespaces
Some webservices require you to add specific headers to your request (i.e. for authentication). In the CFML reference you can find a function AddSOAPRequestHeader which can do this for you. The problem is that the documentation is not always very clear about HOW you should use this.
My problem was that the header should use some custom namespaces and some default namespaces, here is how you should do this.
My SOAP header should look like this:
<soapenv:header>
<ws:authenticationheader>
<username>[username here]</username>
<password>[password here]</password>
</ws:authenticationheader>
</soapenv:header>
XmlHeader = XmlNew();
XmlHeader.xmlRoot = XmlElemNew(XmlHeader,"http://www.url-to-ns","ws:AuthenticationHeader");
XmlHeader.xmlRoot.XmlChildren[1] = XmlElemNew(XmlHeader,"","username");
XmlHeader.xmlRoot.XmlChildren[2] = XmlElemNew(XmlHeader,"","password");
XmlHeader.xmlRoot.username.XmlText = "[username here];
XmlHeader.xmlRoot. username .XmlAttributes['xsi:type'] = "xsd:string";
XmlHeader.xmlRoot.Password.XmlText = "[password here]";
XmlHeader.xmlRoot.Password.XmlAttributes['xsi:type'] = "xsd:string";
AddSOAPRequestHeader(varnameOfWS," http://www.url-to-ns ","ws:AuthenticationHeader",XmlHeader,false);
result = varnameOfWS.doSomething();
From the CF documentation:
Here is the soap header using soap_req = getSOAPRequest(varnameOfWS);
<soapenv:Header>
The namespace definition is valid for the web service which was my goal. I would rather see the definition in the soapenv:Envelope so if anyone knows how to do this please let me know! :)
My problem was that the header should use some custom namespaces and some default namespaces, here is how you should do this.
My SOAP header should look like this:
<soapenv:header>
<ws:authenticationheader>
<username>[username here]</username>
<password>[password here]</password>
</ws:authenticationheader>
</soapenv:header>
There is a namespace "ws" defined in the soapenv:Envelope pointing to a custom namespace. It is still (as far as I could research) impossible to define this in the soapenv. Second best is to define this in the header itself.
XmlHeader = XmlNew();
XmlHeader.xmlRoot = XmlElemNew(XmlHeader,"http://www.url-to-ns","ws:AuthenticationHeader");
XmlHeader.xmlRoot.XmlChildren[1] = XmlElemNew(XmlHeader,"","username");
XmlHeader.xmlRoot.XmlChildren[2] = XmlElemNew(XmlHeader,"","password");
XmlHeader.xmlRoot.username.XmlText = "[username here];
XmlHeader.xmlRoot. username .XmlAttributes['xsi:type'] = "xsd:string";
XmlHeader.xmlRoot.Password.XmlText = "[password here]";
XmlHeader.xmlRoot.Password.XmlAttributes['xsi:type'] = "xsd:string";
AddSOAPRequestHeader(varnameOfWS," http://www.url-to-ns ","ws:AuthenticationHeader",XmlHeader,false);
result = varnameOfWS.doSomething();
From the CF documentation:
XmlElemNew(xmlObj[, namespace], childName)The trick is to add the namespace alias to childName parameter using the format "[alias]:childname", the namespace alias then is automatically added.
Here is the soap header using soap_req = getSOAPRequest(varnameOfWS);
<soapenv:Header>
<ws:AuthenticationHeader
soapenv:actor=""
soapenv:mustUnderstand="0"
xmlns:ws="http://www.url-to-ns">
<username xmlns="" xsi:type="xsd:string">[username here]</username>
<password xmlns="" xsi:type="xsd:string">[password here]</password>
</ws:AuthenticationHeader>
</soapenv:Header>
The namespace definition is valid for the web service which was my goal. I would rather see the definition in the soapenv:Envelope so if anyone knows how to do this please let me know! :)
Wednesday, April 4, 2012
A pinout database of any plug
This is a great initiative: http://pinouts.ru/
I have an old computer power supply lying around which I want to repurpose for a DIY electronics project. But which pin is what? I can try my volt meter on every pin, but using this site is much easier!
This site contains a database with more than 1400 descriptions of hardware pinouts, cables, connectors and even some schemes. Everything is nicely categorized and searchable. You can even submit your own pinouts if you think something is missing!
I have an old computer power supply lying around which I want to repurpose for a DIY electronics project. But which pin is what? I can try my volt meter on every pin, but using this site is much easier!
This site contains a database with more than 1400 descriptions of hardware pinouts, cables, connectors and even some schemes. Everything is nicely categorized and searchable. You can even submit your own pinouts if you think something is missing!
Thursday, May 5, 2011
Install Flash builder 4.5 standalone as an Eclipse plugin
I noticed that there is no download link for the Flash Builder 4.5 Eclipse plugin as it exists with version 4. It seems that a separate plugin installer is no longer necessary.
Here are the steps:
1. Install the standalone version.
2. Go to the program folder of Flash builder 4.5 (program files\Adobe\Adobe Flash Builder 4.5)
3. Then go to the folder "utilities" and execute "Adobe Flash Builder 4.5 Plug-in Utility"
4. Point the installer to your Eclipse folder
Next, next, OK, next, next, done!
Here are the steps:
1. Install the standalone version.
2. Go to the program folder of Flash builder 4.5 (program files\Adobe\Adobe Flash Builder 4.5)
3. Then go to the folder "utilities" and execute "Adobe Flash Builder 4.5 Plug-in Utility"
4. Point the installer to your Eclipse folder
Next, next, OK, next, next, done!
Friday, March 18, 2011
ColdFusion queries and SQL comment
Here's one problem I experienced using a query in ColdFusion which was working perfectly in SQL server manager, but refused to work in ColdFusion.
The query was something like:
SELECT * --some comment
FROM users
WHERE user_id = 1
The query would only work if the comment is removed. The source of the problem is that ColdFusion removes all the line breaks in a query before executing. In this case only "SELECT *" would be executed which results (luckily) in a SQL error.
Good to know this before I tried the following query:
DELETE
FROM users --some comment
WHERE user_id = 1
Note: Normally you would use a SQL param and replace it with queryService.addParam(), this would result in an error because the param could not be found.
To work around this problem use /* and */ for SQL comment, or strip all your comments in SQL if you execute it through ColdFusion.
The query was something like:
SELECT * --some comment
FROM users
WHERE user_id = 1
The query would only work if the comment is removed. The source of the problem is that ColdFusion removes all the line breaks in a query before executing. In this case only "SELECT *" would be executed which results (luckily) in a SQL error.
Good to know this before I tried the following query:
DELETE
FROM users --some comment
WHERE user_id = 1
Note: Normally you would use a SQL param and replace it with queryService.addParam(), this would result in an error because the param could not be found.
To work around this problem use /* and */ for SQL comment, or strip all your comments in SQL if you execute it through ColdFusion.
Tuesday, August 31, 2010
Modifying a column in SQL manager, the right way
If you have a column of a table that needs to be changed, don't always go to the modify table page in SQL manager to do your changes. I tried something simple as increasing the column size of a nvarchar field, but the update kept on giving timeouts in the SQL manager. Then I tried the generate SQL script button to see what SQL manager was trying to do. The contents gave me an idea why I was getting timeouts:
-alter the table:
-drop constraints
-drop triggers
-create temporary table with new column sizes/fields
-add defaults from table to temp table
-add constraints from table to temp table
-add index to temp table
-insert all values from original table to temp table
-drop relationships from original table
-drop original table
-rename temp table name to original table name
-add relationships to temp table
Which it needed to do is:
ALTER TABLE sometablename
ALTER COLUMN somecolumnname
nvarchar(100) NULL;
Next time if I modify a table with much data, or a lot of relationships and/or constraints I will stay clear of the SQL manager "modify table" dialog.
-alter the table:
-drop constraints
-drop triggers
-create temporary table with new column sizes/fields
-add defaults from table to temp table
-add constraints from table to temp table
-add index to temp table
-insert all values from original table to temp table
-drop relationships from original table
-drop original table
-rename temp table name to original table name
-add relationships to temp table
Which it needed to do is:
ALTER TABLE sometablename
ALTER COLUMN somecolumnname
nvarchar(100) NULL;
Next time if I modify a table with much data, or a lot of relationships and/or constraints I will stay clear of the SQL manager "modify table" dialog.
Tuesday, August 3, 2010
Query of queries weirdness
I was playing around with the query service object when I found some strange behavour. It looks like there is a differency between the query object and the QueryNew() object.
See the test case below:
//test case for query of queries usings querynew and query object:
//Make query object with queryNew()
qUsers = queryNew("usename,userID","varChar,integer");
queryAddRow(qUsers);
querySetCell(qUsers,"usename","Jorrit");
querySetCell(qUsers,"userID",1);
queryAddRow(qUsers);
querySetCell(qUsers,"usename","Ben");
querySetCell(qUsers,"userID",2);
queryAddRow(qUsers);
querySetCell(qUsers,"usename","Tom");
querySetCell(qUsers,"userID",3);
writeDump(qUsers);
queryService = new Query();
//queryService.setName("qGetUserByID");
queryService.setDBType("query");
queryService.addParam(name="userID", cfsqltype="cf_sql_integer", value="1");
SaveContent variable="queryBody" {
WriteOutput("SELECT userID, usename ");
WriteOutput("FROM qUsers ");
WriteOutput("WHERE userID = :userID ");
}
queryService.setSql(queryBody);
test = queryService.execute();
writeDump(test);
/*
The code above will result in an error
Error Executing Database Query.
Query Of Queries runtime error.
Table named qUsers was not found in memory. The name is misspelled or the table is not defined.
*/
See the test case below:
//test case for query of queries usings querynew and query object:
//Make query object with queryNew()
qUsers = queryNew("usename,userID","varChar,integer");
queryAddRow(qUsers);
querySetCell(qUsers,"usename","Jorrit");
querySetCell(qUsers,"userID",1);
queryAddRow(qUsers);
querySetCell(qUsers,"usename","Ben");
querySetCell(qUsers,"userID",2);
queryAddRow(qUsers);
querySetCell(qUsers,"usename","Tom");
querySetCell(qUsers,"userID",3);
writeDump(qUsers);
queryService = new Query();
//queryService.setName("qGetUserByID");
queryService.setDBType("query");
queryService.addParam(name="userID", cfsqltype="cf_sql_integer", value="1");
SaveContent variable="queryBody" {
WriteOutput("SELECT userID, usename ");
WriteOutput("FROM qUsers ");
WriteOutput("WHERE userID = :userID ");
}
queryService.setSql(queryBody);
test = queryService.execute();
writeDump(test);
/*
The code above will result in an error
Error Executing Database Query.
Query Of Queries runtime error.
Table named qUsers was not found in memory. The name is misspelled or the table is not defined.
*/
Monday, August 2, 2010
ColdFusion ignores typo in for loop statement
I was making a simple XML iteration in script using a for loop, but it only returned one element in stead of all the elements. In a further inspection I discovered a typo which was not reported by ColdFusion.
Here is the for loop:
for (sCount=1; sCount<+arrayLen(xmlSomething["anotherElement"]); sCount++){
}
The problem is the <+ operator which should be <=
But no error report, just the first element that is returned. I wonder why!
Here is the for loop:
for (sCount=1; sCount<+arrayLen(xmlSomething["anotherElement"]); sCount++){
}
The problem is the <+ operator which should be <=
But no error report, just the first element that is returned. I wonder why!
Thursday, July 15, 2010
Coldfusion 9 problems
This is to make a note which problems I encountered with ColdFusion 9:
SpreadSheetRead has no spreadsheet to query possibility.
returns a query, but with the script function there is no option so it only returns an Excel object:
excelObj = SpreadSheetRead('c:\some.xls',1);
Next stop, the query object with double single quotes:
queryService = new Query();
queryService.setName("qUserExists");
queryService.setDataSource(application.settings.DSN);
queryService.addParam(name="userName", cfsqltype="cf_sql_varchar", value="someusername");
SaveContent variable="queryBody" {
WriteOutput("SELECT TOP 1 CASE ISNULL(U.firstname, '') WHEN '' THEN '*no firstname*' ELSE U.firstname END AS lastname ");
WriteOutput("FROM Users U ");
WriteOutput("WHERE U.Username = :userName ");
}
queryService.setSql(queryBody);
qUserExists = queryService.execute();
Don't mind the uglyness of the query, it is there to prove a bug. The query will return an error. If you see the details of the error and look at the executed query you will see that the two single quotes are replaced by one. So ISNULL(U.firstname, '') will be executed as ISNULL(U.firstname, ').
If someone knows a solution, please let me know.
UPDATE: The query issue is a known bug (80210) and is resolved in update 9.0.1
SpreadSheetRead has no spreadsheet to query possibility.
excelObj = SpreadSheetRead('c:\some.xls',1);
queryService = new Query();
queryService.setName("qUserExists");
queryService.setDataSource(application.settings.DSN);
queryService.addParam(name="userName", cfsqltype="cf_sql_varchar", value="someusername");
SaveContent variable="queryBody" {
WriteOutput("SELECT TOP 1 CASE ISNULL(U.firstname, '') WHEN '' THEN '*no firstname*' ELSE U.firstname END AS lastname ");
WriteOutput("FROM Users U ");
WriteOutput("WHERE U.Username = :userName ");
}
queryService.setSql(queryBody);
qUserExists = queryService.execute();
Don't mind the uglyness of the query, it is there to prove a bug. The query will return an error. If you see the details of the error and look at the executed query you will see that the two single quotes are replaced by one. So ISNULL(U.firstname, '') will be executed as ISNULL(U.firstname, ').
If someone knows a solution, please let me know.
UPDATE: The query issue is a known bug (80210) and is resolved in update 9.0.1
Labels:
Coldfusion,
Coldfusion 9,
query,
spreadsheetread
Wednesday, July 7, 2010
Using database default values in ColdFusion ORM
I stumbled upon a problem when I was using ORM on a SQL table which has a default value (column not null, default value 0). The problem is that ORM does not accept a value which isn't set because then it will insert it as NULL.
Example:
/**
* @persistent true
* @entityName UserError
* @table UserErrors
* @schema dbo
*/
component output="false"
{
property name="user_id" column="user_id" type="numeric" ormtype="int" fieldtype="id" generator="identity";
property name="error_count" column="error_count" type="numeric" ormtype="int"; //column with default value
}
The step for me was to force that you can set this value as NULL, which caused an error:
property name="error_count" column="error_count" type="numeric" ormtype="int" notnull="false" ;
Instead of an ORM error you get a database error. So the next try is to tell ORM not to use this:
property name="error_count" column="error_count" type="numeric" ormtype="int" persistent="false" ;
This worked for the insert because the value was set correctly in the database. The problem is that you cannot retrieve the value after it is inserted.
So the next step is to modify the data before it is inserted. In the component I added the folowing function:
public void function preInsert() {
if(isNull(this.getError_count()))
this.setError_count(0);
}
Now I get an error converting char to int. This gives me a clue that the preInsert function is executed. So now I have to force ColdFusion to use int for the Error_count default value:
public void function preInsert() {
if(isNull(this.getError_count()))
this.setError_count(javacast("int",0));
}
Now it is working as a charm.
The only problem is that you have two places where your database defaults exists. This is something to keep in mind if you are changing databse default values. It is working for me, but it is not ideal.
If I find a better solution I will post it here. Suggestions are welcome in the comments.
Example:
/**
* @persistent true
* @entityName UserError
* @table UserErrors
* @schema dbo
*/
component output="false"
{
property name="user_id" column="user_id" type="numeric" ormtype="int" fieldtype="id" generator="identity";
property name="error_count" column="error_count" type="numeric" ormtype="int"; //column with default value
}
The step for me was to force that you can set this value as NULL, which caused an error:
property name="error_count" column="error_count" type="numeric" ormtype="int" notnull="false" ;
Instead of an ORM error you get a database error. So the next try is to tell ORM not to use this:
property name="error_count" column="error_count" type="numeric" ormtype="int" persistent="false" ;
This worked for the insert because the value was set correctly in the database. The problem is that you cannot retrieve the value after it is inserted.
So the next step is to modify the data before it is inserted. In the component I added the folowing function:
public void function preInsert() {
if(isNull(this.getError_count()))
this.setError_count(0);
}
Now I get an error converting char to int. This gives me a clue that the preInsert function is executed. So now I have to force ColdFusion to use int for the Error_count default value:
public void function preInsert() {
if(isNull(this.getError_count()))
this.setError_count(javacast("int",0));
}
Now it is working as a charm.
The only problem is that you have two places where your database defaults exists. This is something to keep in mind if you are changing databse default values. It is working for me, but it is not ideal.
If I find a better solution I will post it here. Suggestions are welcome in the comments.
Subscribe to:
Posts (Atom)