tag:blogger.com,1999:blog-85898042065493678832023-11-16T16:38:59.735+00:00Those Yaks Won't Shave ThemselvesSoftware development notes especially observations on Axe sharpening vs. Yak shaving, how to tell the difference and where to focus the time [amongst other observations].Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-8589804206549367883.post-70964071297434999502014-01-21T22:13:00.000+00:002014-01-23T13:07:53.407+00:00My C# (Unity3D) Assert()/Log() signature combines Conditional and pre-processorSomeone queried my logging method signature in a patch I offered recently so I thought I'd share the technique and explanation. Forewarnings:<br />
<br />
<ul><li>it's C# (WHAT?! When did I switch? Explanation to come, I guess!)</li>
<li>it's for performance (so sacrifices some immediate clarity to that mistress).</li>
</ul><br />
<br />
<pre class="brush:csharp; gutter:false">#if !DEBUG
[System.Diagnostics.Conditional("UNITY_EDITOR")]
#endif
public static void Assert(bool comparison, string messageFmt, params System.Object[] args) { ... }
// also used on logging
</pre><br />
An explanation in two parts, (1) the Conditional and (2) how the #if interacts with it.<br />
<br />
<a name='more'></a><br />
1. The Conditional is processed by the CLR virtual machine. When the condition it includes is true (i.e. UNITY_EDITOR is defined), the method is invoked normally; else the call-site (where the method is invoked), is removed from the instruction flow -- it's as if the method call never existed! You can see how this has benefits for performance!<br />
Normally, obviously this would mean "logging in Editor, not outside".<br />
<br />
2. By couching the above within a the "#if !DEBUG" we say only do this if DEBUG is *NOT* set. The result is that when DEBUG *IS* set, the method always exists and looks just like a normal method (and the call-sites look normal, too).<br />
<br />
Thus the two together mean Debug builds and the Editor get logging but non-Debug builds only have logging in the Editor.<br />
<br />
EDIT: Sadly, "Debug builds" here doesn't mean simply clicking the "Debug Build" option in the Build Settings. Instead, one must add "DEBUG" to the "Scripting Define Symbols" (search in the "<a href="http://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html">Platform Dependent Compilation</a>" page).<br />
<br />
LMK if you see errors or have concerns, queries, ideas, suggestions, etc.Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-53181721055331288412012-05-24T17:36:00.000+01:002012-05-24T17:36:31.024+01:00HeliDartris begunNew idea for a game (because you can never have too many projects on the go!) Working title is HeliTetris -- play tetris-like line making game using the winch under a helicopter, probably coupled with gravitational sensor data on phones and tablets. How hard could it be? :-)<br />
<br />
Decided to try prototyping/writing it in Google's new <a href="http://www.dartlang.org/">Dart language</a>. I'd heard of this several months back but 2 weeks back, my interest was galvanized by the <a href="http://www.london-gtug.org/Venue/happy-hour---global-dart-hackathon">Dart hackathon</a>! I went along and we had a stab at a multi-player PacMan clone. Not a bad effort given we wrote everything from scratch and hadn't touched Dart before then! (1 guy had written a little and I read the docs on the 30m train journey in!) My conclusion: Dart has great potential. More approachable than Scala -- my other favourite "I hope this is the future" language.<br />
<br />
Anyway, <a href="http://www.sethladd.com/">Seth Ladd</a> had mentioned there was a <a href="http://box2d.org/">Box2D</a> port (via the <a href="http://www.jbox2d.org/">Java port</a>) so what better platform to prototype/write in for cross-platform productivity?<br />
<br />
(My <b><i>opinion</i></b>: JavaScript is just frustratingly badly tooled -- once you get above a certain project size, it sits the un-fun-dark-side of hackyness. Even when kept well structured (which it doesn't help you with), it just becomes more and more work (*1). Dart's optional strong-typing means decent toolability (like Java and Scala). Let's see how it bears out in practise, though!) <br />
<br />
*1: Perhaps it's time for "Big H Notation" which represents how developer headache scales with increases in size of project. Yeah, it could be described as how complexity scales, but let's face it, we don't mind some complexity without the headache! What would you propose for different languages? Hm, this feels like a Twitter/G+ question!<br />
<br />
Anyway, for a bit of a change, I decided to both (a) try the <a href="http://en.wikipedia.org/wiki/Pomodoro_Technique">Pomodoro technique</a> and (b) keep a development blog. Let me know what you think -- good and 'suggested changes' ;-)<br />
<br />
15:00 start on Linux<br />
15:10 <a href="http://www.dartlang.org/docs/editor/">IDE installed</a><br />
15:15 <a href="http://code.google.com/p/dartbox2d/">box2d library found</a> and downloaded (cloned from Google Code Git).<br />
15:20 still trying to run demos<br />
15:30 Don't use Dart Editor integrated webserver, use file path:<br />
<pre class="brush:text; gutter:false">file:///home/username/Dev/Dart/Libs/dartbox2d/demos/demos.html?demo=BallCage</pre>
15:34 Discovered bug in library for all demos "<span style="font-family: 'Courier New', Courier, monospace;">UnsupportedOperationException: Cannot add to a non-extendable array</span>":<br />
<pre class="brush:text; gutter:false">Exception: UnsupportedOperationException: Cannot add to a non-extendable array
Stack Trace: 0. Function: 'ObjectArray.add' url: 'bootstrap_impl' line:125 col:5
1. Function: 'BroadPhase._bufferMove@3b3cfbc8' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/lib/collision/broadphase/BroadPhase.dart' line:215 col:58
2. Function: 'BroadPhase.createProxy' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/lib/collision/broadphase/BroadPhase.dart' line:71 col:16
3. Function: 'Fixture.createProxy' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/lib/dynamics/Fixture.dart' line:96 col:35
4. Function: 'Body.createFixture' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/lib/dynamics/Body.dart' line:189 col:26
5. Function: 'Body.createFixtureFromShape' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/lib/dynamics/Body.dart' line:221 col:25
6. Function: 'BlobTest.initialize' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/demos/BlobTest.dart' line:47 col:36
7. Function: 'BlobTest.main' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/demos/BlobTest.dart' line:29 col:20
8. Function: '::main' url: 'file:///home/username/Dev/Dart/Libs/dartbox2d/demos/BlobTest.dart' line:101 col:16
</pre>
(started trying to debug. Why doesn't the debugger breakpoint in this library!? Hm, investigate more later. <span style="font-family: 'Courier New', Courier, monospace;">print()</span> it is for now = bletch! 15:39 no <span style="font-family: 'Courier New', Courier, monospace;">typeof</span>!? Ah, reflection still in development. Workaround? <span style="font-family: 'Courier New', Courier, monospace;">print("List?: "+ moveBuffer is List) </span>can't be right?!)<br />
15:50 Bug found -- <span style="font-family: 'Courier New', Courier, monospace;">new List(SIZE)</span> is a fixed-length list! Is that expected by 2d author?<br />
15:55 DartBox2D authors haven't stuck to Java Box2D form here -- looks like they relied on List being dynamic.<br />
16:02 Decided to try switching to dynamically-sized list.<br />
16:10 Better. Now different error to do with <span style="font-family: 'Courier New', Courier, monospace;">requestAnimationFrame()</span> having extra param. Luckily, hit this before. Scratch param! 5 of this same error -- removed all.<br />
<i>Man, this new IDE version performs terribly on compile!!! Quick Google doesn't show obvious bug about this. Maybe check later?</i><br />
16:12 Woohoo, works. Time for a commit? Not done with Google Code Git before!<br />
16:47 <a href="http://code.google.com/r/rupertkey-dartbox2d-20120524/">Cloned</a>, committed, learnt Google Code Git, pushed, <a href="https://groups.google.com/d/msg/dartbox2d-discuss/TYe-f-KkCMA/8uBgelLWF_MJ">e-mailed group</a>.<br />
<br />
1 pomodoro? <br />
<br />
17:19 Blog written. Hope you enjoyed as much as I did!Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-1217801746817503892011-10-15T13:22:00.000+01:002011-10-15T13:22:23.485+01:00Android validation (decompilation) toolsSo Jenkins is building and archiving lovely APKs with timestamps in <span style="font-family: "Courier New",Courier,monospace;">versionName</span>! People are testing directly out of DropBox. Got a bug report but need to see which APK it came from!<br />
Goal: Extract human-readable <span style="font-family: "Courier New",Courier,monospace;">versionName </span>from APK.<br />
Two-liner answer after the break!<br />
<a name='more'></a><br />
The answer is very simple...<br />
<ol>
<li>Unzip the <span style="font-family: "Courier New",Courier,monospace;">AndroidManifest.xml</span> from the APK<br />
<span style="font-family: "Courier New",Courier,monospace;">unzip MyAPK.apk AndroidManifest.xml</span></li>
<li>Convert the binary XML to human-readable<br />
<i>(link to JAR in references, below)</i><br />
<span style="font-family: "Courier New",Courier,monospace;">java -jar A2XMLPrinter2.jar AndroidManifest.xml > AndroidManifest.text.xml</span></li>
</ol>
<span style="font-size: large;"><b>Background</b></span><br />
The Android XML files are converted from text to binary form for more efficient on-device use. UNIX's "<span style="font-family: "Courier New",Courier,monospace;">file</span>" command (which informs of file type by checking its magic number) opines these binary XML files are "<span style="font-family: "Courier New",Courier,monospace;">DBase 3 data file</span>".<br />
<br />
While investigating, I came across answers to how to check obfuscation-level (which I'd also wondered about).<br />
<ol>
<li>De-dex your APK<br />
<span style="font-family: "Courier New",Courier,monospace;">dex2jar.sh MyAPK.apk</span><br />
(or <span style="font-family: "Courier New",Courier,monospace;">dex2jar.<i>bat</i> MyAPK.apk</span> if you're stuck on Windoze)</li>
<li>Decompile the Java class files<br />
<i>(in this case, view in one step.)</i><br />
<span style="font-family: "Courier New",Courier,monospace;">jd-gui MyAPK_dex2jar.jar</span></li>
</ol>
I know I've used an Eclipse-based Java decompiler in the past. If anyone's interested / I come across the need, I'll update this post with the Eclipse version.<br />
<br />
HTH!<br />
<br />
<span style="font-size: large;"><b>References</b></span><br />
<table border="1"><tbody>
<tr><td colspan="3"><b>Tools: </b></td></tr>
<tr><td>A2XMLPrinter2 </td><td><a href="http://code.google.com/p/android4me/downloads/list">project home</a> </td><td>Convert Android compiled XML file to human-readable (<a href="http://code.google.com/p/android4me/downloads/detail?name=AXMLPrinter2.jar&can=2&q=">download location</a>)</td></tr>
<tr><td>Dex2Jar </td><td><a href="http://code.google.com/p/dex2jar/">project home</a> </td><td>Convert DEX file (APK) to JAR (class files) </td></tr>
<tr><td>JD-GUI </td><td><a href="http://java.decompiler.free.fr/?q=jdgui">project home</a> </td><td>Java decompiler GUIc</td></tr>
<tr><td colspan="3"><b>How-to descriptions:</b></td></tr>
<tr><td>XDA Developers' "<a href="http://forum.xda-developers.com/showthread.php?t=514412">AXMLPrinter2 - Convert Android binary XML to human-readable XML</a>" thread. </td><td></td><td><br /></td></tr>
<tr><td>AndroidOrigin's how "<a href="http://androidorigin.blogspot.com/2011/02/dex-format-to-jar-format.html">.dex format to .jar format</a>" blog. </td><td></td><td>Not sure why he does it in Eclipse when CLI works perfectly well but... ?</td></tr>
</tbody></table>
<br />
p.s. I'm preparing a post about setting-up Jenkins for good Android building (i.e. "real software engineering" vs. "hacking and guessing" ;-) ). It's kind'a long so it'll be retro-posted after/before this one.Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-85207431652045150212011-08-12T14:03:00.002+01:002011-08-23T18:53:20.635+01:00Eclipse Mylyn / Bugzilla "resolution required" UX bugletEclipse Mylyn / Bugzilla error... <br />
<pre class="brush:text;; gutter:false; toolbar:false">Submit failed: resolution required: A valid resolution is required to mark bugs as RESOLVED.</pre>
... requires specific steps to avoid. <a href="http://www.urbandictionary.com/define.php?term=tl%3Bdr">TL;DR</a> solution and notes after the break.<br />
<a name='more'></a><br />
The steps:<br />
<ol>
<li>Ensure notes saved & submitted </li>
<li>Ensure good status and fully synchronized, i.e: </li>
<ol>
<li>Ensure status IN_PROGESS (CONFIRMED known to work too)</li>
<li>Submit</li>
<li>Synchronize incoming changes</li>
</ol>
<li>Resolve as - FIXED </li>
</ol>
If this doesn't seem to work...<br />
<ol>
<li>Ensure all but status change saved (e.g. notes saved),</li>
<li>Discard outgoing changes</li>
<li>Do a full repository synchronize</li>
<li>[<i>potentially</i> synchronize incoming changes -- should be unlikely!] </li>
<li>Set status FIXED</li>
<li>Submit</li>
</ol>
If this <i>still</i> doesn't work, the last inexplicable rite is:<br />
<ol>
<li>With status as FIXED (which we know fails)</li>
<li>Set status back to IN_PROGRESS (yes, not discard!)</li>
<li>Submit (yes, submit the same status it already is)</li>
<li>Set status to FIXED</li>
<li>Submit!</li>
</ol>
<ol>
</ol>
Let me know if you find more tips / etc!<br />
<ol>
</ol>
<hr size="1" />
<span style="font-size: large;"><b>Investigation notes</b></span><br />
That seems to be it. Can't say I'm happy with this but it works for now.<br />
Here follow some notes from investigating in case useful to others / future-me... <br />
<ul>
<li>Applying <a href="http://www.wireshark.org/">Wireshark</a>:</li>
<ul>
<li>POST /bugzilla/process_bug.cgi HTTP/1.1 </li>
<li>Some interesting parameters passed:</li>
<ul>
<li>bug_id=<br />everconfirmed=<br />resolution=<br />bug_status=<br />resolve=<br />resolutionInput=<br />dependson=<br />dup_id=<br />classification_id=<br />... (lots of other params)</li>
<li>The blank "resolution" and set "resolve" and "resolutionInput" fields are interesting.</li>
</ul>
<li>Determined working steps above. Now...</li>
<ul>
</ul>
<li>Difference between FAIL and SUCCESS:
<table border="1">
<tbody>
<tr><th>Field</th><th>Fail</th><th>Succeed</th></tr>
<tr><th>resolution</th><td>(blank -- present but no value)</td><td>FIXED</td></tr>
<tr><th>resolve</th><td>FIXED</td><td>(field absent)</td></tr>
<tr><td align="center" colspan="3">(others same)</td></tr>
<tr><th>bug_status</th><td colspan="2">RESOLVED (same)</td></tr>
<tr><th>resolutionInput</th><td colspan="2">FIXED (same)</td></tr>
<tr><th>everconfirmed</th><td colspan="2">1 (same)</td></tr>
<tr><td align="center" colspan="3">...</td></tr>
</tbody></table>
</li>
</ul>
<li><a href="http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Bug.html#update">http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Bug.html#update</a></li>
<ul>
<li style="font-family: "Courier New",Courier,monospace;">121 (Resolution Required)<br />You tried to set the status field to a closed status, but you didn't specify a resolution.</li>
<li>(yup, that agrees with my table above) </li>
</ul>
<li><a href="http://www.bugzilla.org/docs/tip/en/html/parameters.html">http://www.bugzilla.org/docs/tip/en/html/parameters.html</a> </li>
<ul>
<li style="font-family: "Courier New",Courier,monospace;">noresolveonopenblockers<br />This option will prevent users from resolving bugs as FIXED if they have unresolved dependencies. Only the FIXED resolution is affected. Users will be still able to resolve bugs to resolutions other than FIXED if they have unresolved dependent bugs.</li>
<li>Could see this being potential factor but not for my situation</li>
</ul>
</ul>
If anyone (including future-me) needs, I might investigate the Mylyn source to see what can be done to reduce probability of seeing this. Today, that's definitely a major yak ;-)<br />
<ul><ul></ul>
</ul>
Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-56730621994173131992011-08-08T20:27:00.000+01:002011-08-08T20:27:21.023+01:00Using a Linux android emulator serverSituation: You have a fast lots-of-memory <i><b>Linux</b></i> desktop box (perhaps remote) to run your Android emulators on and a desktop machine running your IDE. How best to debug remotely?<br />
SSH port-forwarding instructions for Windows (and others) after the break.<br />
<a name='more'></a><br />
So <i><b>ideally</b></i> one could tell the emulator to listen for connections on a non-localhost address but convincing the emulator to do this seems hard (*A). Instead, use good old SSH port tunnelling to solve it for you!<br />
<br />
<br />
Tell your local SSH to forward local connections to 5555 to your Linux server's 5555 (or better, forward local 5559 to remote 5555 so you can still use local emulators on 5555) . Since most Windows users are likely using <a href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/">PuTTY</a>, this is done by...<br />
<ol>
<li> editing the settings</li>
<ol>
<li>either for your stored connection </li>
<li>or via "System Menu | Change settings..."</li>
</ol>
<li>select "Connection | SSH | Tunnels"</li>
<li>under "Add new forwarded port:" populate as follows:</li>
<ol>
<li>Source port: <span style="font-family: "Courier New",Courier,monospace;">5559</span></li>
<li>Destination: <span style="font-family: "Courier New",Courier,monospace;">localhost:5555</span></li>
</ol>
<li>Hit "Add"</li>
<li>[If updating a saved profile, don't forget to go save it!]</li>
</ol>
Once done, you need to tell local ADB to connect to the new tunnel. Run command-line (either <WINDOWS-R> or in a DOS box)...<br />
<blockquote>
<span style="font-family: "Courier New",Courier,monospace;">adb connect :5559</span></blockquote>
...and you should be set. "<span style="font-family: "Courier New",Courier,monospace;">adb devices</span>" and "<span style="font-family: "Courier New",Courier,monospace;">adb logcat -d</span>" should show devices and remote logs respectively and Eclipse's DDMS view (etc) should now show logging from the Linux-based Android emulator. (if not, try "<span style="font-family: "Courier New",Courier,monospace;">adb kill-server</span>" then "<span style="font-family: "Courier New",Courier,monospace;">adb connect :5559</span>" again.)<br />
<br />
HTH!<br />
<br />
*A: The CLI provides for changing the port (with <span style="font-family: "Courier New",Courier,monospace;">-port</span>!) but not to specify which address (interface) to bind to. Obviously, if one can rearrange the default interface, this would likely work. The downsides: that requires root powers and would likely be inadvisable since it'd probably mess with your Linux box's efficiency (since it'd likely route many more packets via full ethernet stack rathern their being sent much faster purely over loopback). Better, we update the emulator code to provide an extra argument to supply bind interface (or somesuch).<br />
<br />
p.s. I can supply SSH CLI instructions but I'm sure anyone on CLI knows how to use man(1) ;-) Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-12820780754728410682011-06-13T17:17:00.010+01:002011-06-13T17:27:10.455+01:00Eclipse eUML2 plugin installation problem and solutionGot red herring errors below when trying to <a href="http://www.soyatec.com/euml2/installation/galileo/index.php">install</a>
Soyatec's excellent UML Eclipse plugin eUML2. Found real answer in the <a href="http://www.soyatec.com/forum/viewtopic.php?t=898&sid=1a1388b502a12114e6b8f28d7bbdee2a">Soyatec forums here</a> -- install GMF (Graphical Modelling Framework) first.<br />
Worked a treat. Errors after the break.<br />
<br />
<a name='more'></a>For saving others from this minor yak, I strongly suspect these errors are red herrings -- hits from <a href="https://bugs.launchpad.net/ubuntu/+source/eclipse/+bug/569224">Ubuntu</a> and <a href="http://wiki.eclipse.org/IRC_FAQ#When_I_try_to_install_a_plug-in.2C_I_get_a_.22Cannot_connect_to_keystore..22_error.2C_what_should_I_do.3F">Eclipse</a> aren't useful (especially obvious since I happened to be on Windows7 rather than my usual Ubuntu this time!!!)<br />
<br />
Error 1:
<br />
<pre class="brush:text"> Cannot connect to keystore.
This trust engine is read only.
Cannot complete the install because one or more required items could not be found.
Software currently installed: eUML2 Free Edition 3.4.0.20091122 (com.soyatec.euml2.free.feature.group 3.4.0.20091122)
Missing requirement: Modeling toolset 2.5.0.20091122 (org.soyatec.tools.modeling 2.5.0.20091122) requires 'bundle org.eclipse.gmf.runtime.notation 0.0.0' but it could not be found
Cannot satisfy dependency:
From: eUML2 Free Edition 3.4.0.20091122 (com.soyatec.euml2.free.feature.group 3.4.0.20091122)
To: org.soyatec.tools.modeling [2.5.0.20091122]
</pre>
<br />
Error 2:
<br />
<pre class="brush:text">java.io.IOException: This trust engine is read only.
at org.eclipse.osgi.internal.service.security.KeyStoreTrustEngine.doAddTrustAnchor(KeyStoreTrustEngine.java:154)
at org.eclipse.osgi.service.security.TrustEngine.addTrustAnchor(TrustEngine.java:50)
at org.eclipse.equinox.internal.provisional.p2.engine.CertificateChecker.checkCertificates(CertificateChecker.java:106)
at org.eclipse.equinox.internal.provisional.p2.engine.CertificateChecker.start(CertificateChecker.java:41)
at org.eclipse.equinox.internal.provisional.p2.engine.phases.CheckTrust.completePhase(CheckTrust.java:43)
at org.eclipse.equinox.internal.provisional.p2.engine.Phase.postPerform(Phase.java:195)
at org.eclipse.equinox.internal.provisional.p2.engine.Phase.perform(Phase.java:78)
at org.eclipse.equinox.internal.provisional.p2.engine.PhaseSet.perform(PhaseSet.java:44)
at org.eclipse.equinox.internal.provisional.p2.engine.Engine.perform(Engine.java:54)
at org.eclipse.equinox.internal.provisional.p2.ui.operations.ProvisioningUtil.performProvisioningPlan(ProvisioningUtil.java:389)
at org.eclipse.equinox.internal.provisional.p2.ui.operations.ProfileModificationOperation.doExecute(ProfileModificationOperation.java:61)
at org.eclipse.equinox.internal.provisional.p2.ui.operations.ProvisioningOperation.execute(ProvisioningOperation.java:37)
at org.eclipse.equinox.internal.provisional.p2.ui.ProvisioningOperationRunner$1.run(ProvisioningOperationRunner.java:94)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
</pre>
<br />
For your amusement, below is the first class diagram I've reverse engineered from [my version of] the Android SyncAdapter example.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_ci784dB1XdAiRRnM0dRleQoimyAW6c3sAxsmLigf-i4L1UaLgpddu2HVr8s6JoqdkZ9ViQg8cB99N5CeBhomWf7ikAbMxPegqR-iUYIe87V2YPZhwvQ5oq7LfLr_FN480PfMrF8rMPBE/s1600/ClassDiagram1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_ci784dB1XdAiRRnM0dRleQoimyAW6c3sAxsmLigf-i4L1UaLgpddu2HVr8s6JoqdkZ9ViQg8cB99N5CeBhomWf7ikAbMxPegqR-iUYIe87V2YPZhwvQ5oq7LfLr_FN480PfMrF8rMPBE/s640/ClassDiagram1.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">UML class diagram of SyncAdapter</td></tr>
</tbody></table>Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-38017231500481476502011-04-23T15:27:00.000+01:002011-04-23T15:27:54.875+01:00Bug: SoapUI fails to add REST Test Method to Test Case when using Resource solely to share parameters[Duplicated from my EviWare/SoapUI forum post <a href="http://www.soapui.org/forum/viewtopic.php?f=13&t=7362&p=21376&sid=ea33d80b1af4988787a88cbe891fc050#p21376">here</a>.]<br />
<br />
Using SoapUI 3.6.1, I ran into same problem as listed here <a class="postlink-local" href="http://www.soapui.org/forum/viewtopic.php?f=2&t=4462&start=15">viewtopic.php?f=2&t=4462&start=15</a> (which I named this topic after).<br />
I downloaded the 3.6.2 nightly and retried. No fix.<br />
OOI,
by opening the project XML in Eclipse, I can see that despite throwing
the same error, if I save, the new testStep does appear in the XML.
I've tried "Resolve" (no errors), loading and reloading, restarting
SoapUI. No help.<br />
Below are more details of the problem some more and a workaround ...<br />
<a name='more'></a><br />
The problem seems to happen when using resources to add parameters to methods.<br />
<br />
<b>Project structure explanation:</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg35bsB9tBDqQDYvX9M-mtmtj3rOhYGl22rYKSRbSo51TAncKv1upSYWfP6-8EVi5Ymp9plNN28g2riZ-E06kvVLbN6Sn5HWLZjSI675vu4631tsXODEoJiZM2mBxwqn4CPmIW_CtBSYapA/s1600/SoapUI.ResourcesForParamAddition.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg35bsB9tBDqQDYvX9M-mtmtj3rOhYGl22rYKSRbSo51TAncKv1upSYWfP6-8EVi5Ymp9plNN28g2riZ-E06kvVLbN6Sn5HWLZjSI675vu4631tsXODEoJiZM2mBxwqn4CPmIW_CtBSYapA/s320/SoapUI.ResourcesForParamAddition.png" width="320" /></a></div>
A set of methods M1 all take parameters x, y & z. Rather than
creating x, y & z in every method in M1, create a resource R1 with
parameters x, y & z and place all M1 methods under it. (they'll
then automatically have parameters x, y & z).<br />
Another set of
methods M2 take all M1 parameters and also all take parameter w. Create
resource R2 under R1 and place M2 under R2. (M2 methods will then
automatically have parameters w, x, y & z).<br />
<br />
The image shows this structure at the bottom where Resource "task-based" has 3 parameters that <span style="font-family: "Courier New",Courier,monospace;">setUrl()</span>
(and its imminent siblings) all use). (In case you're curious, the API
is RememberTheMilk.com, calls all share the same path and are
distinguished by the "method" parameter.)<br />
<br />
<b>Workaround:</b><br />
I recreated the troublesome method (<span style="font-family: "Courier New",Courier,monospace;">setUrl</span> in this case) outside my structure with all the parameters and retried adding to my testcase -- it worked fine.<br />
<br />
<b>Source:</b><br />
I checked the source briefly when the problem happens...
<br />
<pre class="brush:text; gutter:false">Thu Apr 21 11:20:58 BST 2011:ERROR:java.lang.NullPointerException
java.lang.NullPointerException
at com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase.ensureUniqueName(WsdlTestCase.java:312)
at com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase.insertTestStep(WsdlTestCase.java:503)
at com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase.insertTestStep(WsdlTestCase.java:494)
at com.eviware.soapui.impl.wsdl.panels.testcase.WsdlTestCaseDesktopPanel$AddWsdlTestStepAction.run(WsdlTestCaseDesktopPanel.java:698)
</pre>
<pre class="brush:java; first-line:310"> private boolean ensureUniqueName( WsdlTestStep testStep )
{
String name = testStep.getName();
</pre>
It's the top of <span style="font-family: "Courier New",Courier,monospace;">ensureUniqueName()</span> suggesting the <span style="font-family: "Courier New",Courier,monospace;">testStep</span> argument is <span style="font-family: "Courier New",Courier,monospace;">null</span>.
<br />
<pre class="brush:java; first-line:497"> public WsdlTestStep insertTestStep( TestStepConfig stepConfig, int ix, boolean clearIds )
{
WsdlTestStep testStep = createTestStepFromConfig( newStepConfig );
if( !ensureUniqueName( testStep ) )
</pre>
So something went awry with <span style="font-family: "Courier New",Courier,monospace;">createTestStepFromConfig()</span>.
<br />
<pre class="brush:java; first-line:295"> private WsdlTestStep createTestStepFromConfig( TestStepConfig tsc )
{
WsdlTestStepFactory factory = WsdlTestStepRegistry.getInstance().getFactory( tsc.getType() );
if( factory != null )
{
WsdlTestStep testStep = factory.buildTestStep( this, tsc, forLoadTest );
return testStep;
}
else
{
logger.error( "Failed to create test step for [" + tsc.getName() + "]" );
return null;
}
}
</pre>
Assuming <span style="font-family: "Courier New",Courier,monospace;">logger.error()</span> would show in SoapUI's "error log" or "soapUI log" tabs and that error not seen, conclude that successfully got a factory but it built a null testStep.<br />
<br />
I haven't built from source to take this further but hopefully the above will help (a) others get past this problem and/or (b) help Eviware fix the bug / recommend against this practise if considered bad :-)<br />
<br />
Thanks & HTH, R.Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-41017149308453492122011-04-23T15:04:00.001+01:002011-04-23T15:07:37.074+01:00SoapUI aide memoire and groovy scripting (on RTM)A braindump (not a tutorial) on SoapUI including use of Groovy to script parameter generation!<br />
To whet pre-jump appetites, the SoapUI primary structure:<br />
<ul>
<li>Project - houses...</li>
<ul>
<li>Methods - Create these including parameters that need populating later (I'm doing REST atm)</li>
<li>TestSuite - One can only script within a test suite/case so we'll need one</li>
</ul>
<ul><ul>
<li>TestCases - one for each separable chunks of work.<br />Lots of choices but I've mostly used...</li>
<ul>
<li>GroovyScript - code to generate values (like hashes)</li>
<li>PropertyTranfer - Used to copy values between scripts and calls' parameters (REST calls, etc)</li>
<li>Test Request (REST/SOAP/HTTP/JDBC/AMF!) to make actual calls</li>
</ul>
</ul>
</ul>
<ul>
<li>Setup Script and TearDown Script can be placed on TestSuite, TestCase, etc to also house the scripting. (but I've generally found scripts more handy.)</li>
</ul>
<ul>
<li>Project-wide utility methods can only be defined with a SoapUI Pro license (IIUC). Without this, I've ended-up with some copy-and-paste re-use :-( <i>Shame there's no sliding scale from Community to Pro!</i></li>
</ul>
</ul>
Full details after the break and please note this post's a WIP -- perhaps forever! ('90s webpage, anyone? ;-) )<br />
<a name='more'></a>So, the rest of this post is in the context of my RTM Android Sharer but I hope it'll be sufficiently general to be helpful. Why was I using SoapUI when I'm coding Android? Well, I wanted to confirm my understanding of the RememberTheMilk API -- specifically, to test:<br />
<ol>
<li>connectivity</li>
<li>authentication</li>
<li>creating a task with...</li>
<ol>
<li>a URL</li>
<li>a note</li>
<li>a set of tags</li>
</ol>
<li>retrieving a list of tags to auto-suggest for the list above (later)</li>
</ol>
As a long-time basic user of <a href="http://www.soapui.org/">SoapUI</a>, I've been aware that there's Groovy scripting but never found need to use in anger. However, the RTM authentication API signs each call by MD5-hashing a shared-secret, all parameters and values into a parameter called "<span style="font-family: "Courier New",Courier,monospace;">api_sig"</span>. Obviously, this needs some scripting! So, new project steps...<br />
<ol>
<li>Create the basic SoapUI REST structure + methods<br /><i>(may add more detail if people interested / I fear I'll forget)</i></li>
<li>Create a test suite</li>
<li>Create TestCases for separable chunks of work.<br /><i>(logging in, creating a task, etc)</i></li>
<li>Add Properties to Suite/TestCase/... to act as global variables to move data through <i>(bletch!)</i><br />(e.g. <span style="font-family: "Courier New",Courier,monospace;">auth_token</span> needs passing to all calls once received from previous call so stash now and retrieve as described in PropertyTransfer section below)</li>
<li>Add GroovyScript items to do some operations -- in my case the <span style="font-family: "Courier New",Courier,monospace;">api_sig</span> generation.</li>
<li>Add REST Test Requests with both populated and empty parameters</li>
<li>Add PropertyTranfer to move data between steps (see below)</li>
<li>To ensure everything's going well, throw in <a href="http://www.soapui.org/Functional-Testing/getting-started-with-assertions.html">some assertions</a> on the results.<br /><i>(such as XPath <span style="font-family: "Courier New",Courier,monospace;">/rsp/@stat</span> to confirm the root "<span style="font-family: "Courier New",Courier,monospace;">rsp</span>" element has a "<span style="font-family: "Courier New",Courier,monospace;">stat</span>" attribute whose value "<span style="font-family: "Courier New",Courier,monospace;">ok</span>" one places in the "Expected Result" field.)</i></li>
</ol>
Although we've all used SoapUI's capabilities in the past, I still find myself re-learning parts on first use so below follow some aide memoir notes on this delightfully hairy yak :-)<i><br /></i><br />
<ol>
</ol>
<b><span style="font-size: large;">PropertyTransfer</span></b><br />
<br />
Wow, are these powerful!<br />
As mentioned above, I found it handy to create holder-slots on the Test Step (/ Case / Suite depending how widely something was useful) and transferring values from a previous Response to these for future use. Not sure whether that's best practise but it definitely works :-)<br />
<br />
Data transfer slightly different depending upon source...<br />
<ul>
<li>XML Response results:</li>
<ul>
<li>XQuery is optional, XPath is used if not selected and that's plenty powerful!</li>
<li>Retrieve text values with <span style="font-family: "Courier New",Courier,monospace;">/rsp/timeline</span><br />(will retrieve from <span style="font-family: "Courier New",Courier,monospace;"><rsp><timeline>DATA</...></...></span>)</li>
<li>Retrieve attribute values with <span style="font-family: "Courier New",Courier,monospace;">/rsp/@stat</span><br />(will retrieve from <span style="font-family: "Courier New",Courier,monospace;"><rsp stat="DATA"></...></span>)</li>
<li>Some simple mouse/eyeball errors ...</li>
<ol>
<li>Error:<pre class="brush:text; gutter:false">net.sf.saxon.trans.XPathException: XPath syntax error at char 9 in {/rsp/list@id}:
Unexpected token "@" beyond end of expression</pre>
Cause: Missing "/" before "@". Should be <span style="font-family: "Courier New",Courier,monospace;">/rsp/list/@id</span></li>
<li>Error:<pre class="brush:text; gutter:false">Missing match for Source XQuery [/rsp/list/@id]</pre>
Cause: Erroneously ticked XQuery -- you're using XPath but selected to use XQuery. Make up your mind ;-)</li>
<li>Error:<pre class="brush:text; gutter:false">java.lang.reflect.InvocationTargetException</pre>
Cause: Likely both (1) and (2) = Missing "/" and erroneously ticked XQuery.</li>
</ol>
</ul>
<li>Script results:</li>
<ul>
<li>return from your Groovy script and select script result to pull out. It's how I did the MD5 hashing above.</li>
<li>To transfer data into a script, stash the value in a property and retrieve. Rather than using navigation via <span style="font-family: "Courier New",Courier,monospace;">testSuite</span> or <span style="font-family: "Courier New",Courier,monospace;">testCase</span>,
it's usually easier to use the context's expander since it's uniformly
available in all scripts (so doesn't require copy-and-paste editing if
you lack SoapUI Pro for global libraries). E.g:</li>
<ul>
<li>To retrieve a custom property "<span style="font-family: "Courier New",Courier,monospace;">api_key</span>" from the TestSuite, </li>
<li>Rather than ...
<pre class="brush:groovy; gutter:false">def api_key = testSuite.properties."api_key".value;
(which will only work when you have testSuite available which might require navigating to it from other variables) </pre>
</li>
<li>... use ...
<pre class="brush:groovy; gutter:false">def api_key = context.expand('${#TestSuite#api_key}');</pre>
</li>
</ul>
</ul>
</ul>
<ul><ul>
</ul>
</ul>
<span style="font-size: large;"><b>Tips</b></span> <br />
Great tips to have a look at:<br />
<ul>
<li>The docs are a little discontinuous so here're my favourite janky links:</li>
<ul>
<li> <a href="http://www.soapui.org/Scripting-Properties/tips-a-tricks.html#0-1-how-to-get-and-set-properties-from-groovy">soapUI Tips & Tricks</a> (fantastic jumpstart on all scripting!)</li>
<li><a href="http://www.soapui.org/Scripting-Properties/the-soapui-object-model.html">SoapUI object model</a> </li>
</ul>
<li>Note <a href="http://www.soapui.org/apidocs/com/eviware/soapui/support/XmlHolder.html">XmlHolder</a> <i>may</i> not seem to be giving a powerful enough return type (e.g. <span style="font-family: "Courier New",Courier,monospace;">String</span>!). Instead of using its <span style="font-family: "Courier New",Courier,monospace;">getNodeValue(xpath)</span> to get <a href="http://download.oracle.com/javase/1.5.0/docs/api/org/w3c/dom/Node.html">Xml Node</a> then doing details, usually better to make a smarter XPath query that returns exactly what you wanted to test. E.g.</li>
<ul>
<li>To find the <span style="font-family: "Courier New",Courier,monospace;">value</span> attribute of the <span style="font-family: "Courier New",Courier,monospace;">api</span> input field in the <span style="font-family: "Courier New",Courier,monospace;">loginform</span>, </li>
<li>Once one has the XmlHolder by..
<pre class="brush:groovy">import com.eviware.soapui.support.XmlHolder;
log.info "messageExchange: "+ messageExchange;
def holder = new XmlHolder(messageExchange.responseContentAsXml);
assert null != holder;</pre>
</li>
<li>... rather than...
<pre class="brush:groovy; first-line:5">def apiNodeValueAttr = holder.getDomNode("//form[@id='loginform']/input[@name='api']/@value");
assert null != apiNodeValueAttr;
log.info "apiNodeValueAttr: "+ apiNodeValueAttr;
def value = apiNodeValueAttr.getNodeValue();
assert null != value;
log.info "api node value: "+ value;</pre>
</li>
<li>... use...
<pre class="brush:groovy; first-line:5">def apiNodeValue = holder["//form[@id='loginform']/input[@name='api']/@value"];
assert null != apiNodeValue;
log.info "apiNodeValue: "+ apiNodeValue;</pre>
</li>
</ul>
<li>XPath wildcards don't work in 3.6.1 but <a href="http://www.soapui.org/forum/viewtopic.php?f=2&t=6456&p=19280">allegedly fixed in 3.6.2</a>. Tried but doesn't seem to be as of 2011/04/23.</li>
<li><i>Unverified: </i>Disabling Assertions doesn't seem to be saved?</li>
<li><i> ...(maybe done / maybe more to follow as I discover)...</i></li>
</ul>
Whew, lots of SoapUI braindumpage! Hope you found some wheat hidden in my chaff.<br />
p.s. Can sanitize and post the project if it'd be handy. (no, you're not having my RTM API key :-P )Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-3690237688533761372011-04-21T12:27:00.002+01:002011-04-21T13:13:01.296+01:00Tacking to pick up the Droid trade windWell, wow a lot's happened since that last post. My Father died (yep, "<i><span style="font-family: Georgia,"Times New Roman",serif;">To lose one parent, Mr. Worthing, may be regarded as a misfortune. To lose both looks like carelessness.</span></i>"), decided to re-evaluate life and left <a href="http://maldenlabs.com/">Malden Labs</a>. I had a great time there; learned, saw and did lots; met a tonne of interesting people and wouldn't have missed it for anything. However, I always fancied being master and commander of my own boat so am taking The Good Ship <a href="http://www.unreasonablygoodsoftware.com/">UGS</a> (my half-comically, half-seriously named company) to sea. Initially with some Android app and game writing but we'll see which way the wind blows. Android appeals since I've been Java programming since '96 and the current current at last seems strong enough to carry us to promised lands (and/or cities of gold). To top it off, as an ideas person, I'm slightly sickened by the slew of recent business successes that are depressingly (or reassuringly) similar to previous ideas. (I'm sure this isn't unusual but that doesn't make it less sickening ;-) )<br />
<br />
So starting simple and trying to focus on failing fast with delicious early feedback, first projects will be a 2D casual game using <a href="http://www.andengine.org/">AndEngine</a> and a personal-itch scratching Android <a href="http://www.rememberthemilk.com/">RememberTheMilk</a> Sharer utility (surely it's not that hard to catch the SEND intent, offer to store to RTM with some processing to tidy-up common content.)<br />
<br />
Never fear, our regular yak programming will continue (even more so now since I won't be posting on internal blogs and wikis!) but maybe there'll even be some non-yak content! Ok, time for a calming lie down ;-)Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-71133526338199461582011-01-30T13:33:00.012+00:002011-04-22T13:03:50.312+01:00update-alternatives and the Chrome takeover quashFinally got round to understanding Ubuntu's <span style="font-family: "Courier New",Courier,monospace;">/etc/alternatives</span> a <i>little</i> more after installing Chrome made it my default browser!? More details after the jump (another first!) but briefly:<br />
<ul>
<li>List all alternative-able things:<pre class="brush:shell; gutter:false">sudo update-alternatives --get-selections</pre>
</li>
<li>Choose which browser:<br />(these present menu to select from)<pre class="brush:shell; gutter:false">sudo update-alternatives --config x-www-browser
sudo update-alternatives --config gnome-www-browser</pre>
</li>
</ul>
<a name='more'></a><br />
Checking Chrome's <span style="font-family: "Courier New",Courier,monospace;">postinst</span> script, the Chrome developers thought it was a dodgy thing to do, too. They comment (below) that Firefox has too low a priority so concluded: <br />
<pre class="brush:shell; highlight:1; gutter:false">
# /usr/bin/google-chrome 200
# /usr/bin/galeon 120
# /usr/bin/konqueror 100
# /usr/bin/seamonkey 80
# /usr/bin/firefox-3.0 40
# /usr/bin/firefox-2 30</pre>
Love when you get to see bit-company's developers' humanity (what I wouldn't have done back in the day to perceive IBM as human!). The script includes edited comments:<br />
<br />
<blockquote style="font-family: Verdana,sans-serif;">
This is all pretty insane, and the Debian policy manual does not have clear guidelines. While these values should really be keyed off the most popular browser (Firefox), in practice, the most insane setting probably needs to become the lower bound (hi, Galeon), so let's go with the following scheme:<br />
...<br />
Anyone want to poke Firefox to raise their priority?</blockquote>
<br />
Wonder whether the Firefoxes have read this? What's that? It's open-source so I should [damn well] do it myself? Fair. Reminds me I must resume using <a href="http://www.rememberthemilk.com/">RTM</a>! <br />
:-)Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-46611322651391762032010-11-03T12:46:00.001+00:002010-11-03T12:57:50.399+00:00hg rebase or how to move trunk/default changesets to a branchScenario: <br />
One wishes to move changesets on trunk (starting with revision A onwards) to a new branch B.<br />
<br />
<ol>
<li>Enable the Rebase extension for you / the repository per the <a href="http://mercurial.selenic.com/wiki/RebaseExtension">RebaseExtension docs</a></li>
<li>If outstanding changes, commit or shelve them!<br />
(otherwise next step will generate merge request)</li>
<li><code>hg update <A-1></code><br/>(the one before you wish to move to branch B)</li>
<li><code>hg branch B</code></li>
<li><code>hg status</code><br />
confirm output has no actual changes (branch change won't be shown)</li>
<li><code>hg commit -m 'create B'</code></li>
<li><code>hg branches</code><br />
get actual revision for B, we'll call it C</li>
<li><code>hg rebase -s A -d C</code></li>
</ol>
That's it. If insufficiently clear, I can post some screenshots, etc. Do ask but expect delayed response unless you tweet me!Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-79857863619658952682010-10-18T00:06:00.003+01:002011-06-25T13:38:11.472+01:00Error #1069 using namespaced membersError:
<pre class="brush:plain; gutter:false; wrap-lines:true; toolbar:false">ReferenceError: Error #1069: Property myNamespacedProperty not found on a.b.c.MyClass and there is no default value.</pre>
Seen when attempting to access a member (property/method/accessor) of a class that uses a custom namespace, e.g:<br />
<pre class="brush: as3">messaging_internals function getMillisecondsSinceSent():uint {
return getTimer() - _lastSentTime;
}</pre>
Obviously here "<tt>messaging_internals</tt>" is the namespace.<br />
<br />
Answer:<br />
Check that both declaration and use are using <i><b>exactly</b></i> the same definition of the namespace. For example, check that you don't have a duplicate definition!<br />
<br />
We saw this problem when project A had namespace An on methods in class
Ac. Used by project B in class Bc. All looked fine, compiled fine but
unit testing saw Error #1069. Eventually realised that a bad
refactoring had left a second copy of the namespace An in project B
(where it had orignally been), leaving An obscured by the identically
named Bn. Bc was using Bn which failed to resolve to An hence members
in Ac were unreachable!<br />
<i> (Yes, I can add a diagram if anyone wants.) </i><br />
<br />
Obviously ideally the tooling should highlight this.<br />
HTH!Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-68887758021415425982010-10-17T23:54:00.002+01:002011-04-22T13:16:41.880+01:00FlexUnit from both FlashBuilder and FlexMojos for library projectsFlashBuilder leaves its <tt>FlexUnitTestRunnerUI </tt>files in "<tt>src</tt>".<br />
For <tt>packaging:swf</tt> FlexMojos projects, that's fine (*1), it builds them.<br />
<i>*1: OK, it may not be all that fine but it doesn't cause failure.</i><br />
For <tt>packaging:swc</tt> FlexMojos projects, they fail with "Type was not found" etc errors! How to fix, after the break...<br />
<a name='more'></a>The full error they fail with is:
<br />
<pre class="brush:shell; gutter:false">[INFO] --- flexmojos-maven-plugin:4.0-SNAPSHOT:compile-swc (default-compile-swc) @ deleteinbuild ---
[INFO] Flexmojos 4.0-SNAPSHOT
[INFO] Apache License - Version 2.0 (NO WARRANTY) - See COPYRIGHT file
Writing configuration dump to C:\Users\MyUser\Dev\Experiments\MavenDeleteInBuild\target\deleteinbuild-1.0-SNAPSHOT-configs.xml
C:\Users\MyUser\Dev\Experiments\MavenDeleteInBuild\src\FlexUnitApplication.mxml(33): Error: Type was not found or was not a compile-time constant: FlexUnitTestRunnerUI.
<flexui:FlexUnitTestRunnerUI id="testRunner">
C:\Users\MyUser\Dev\Experiments\MavenDeleteInBuild\src\FlexUnitApplication.mxml(18): Error: Accessof undefined property SomeClassTest in package a.b.c.
testsToRun.push(a.b.c.SomeClassTest);
C:\Users\MyUser\Dev\Experiments\MavenDeleteInBuild\src\FlexUnitCompilerApplication.mxml(13): Error: Type was not found or was not a compile-time constant: SomeClassTest.
private var a_b_c_SomeClassTest_obj:a.b.c.SomeClassTest;
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------</pre>
To solve this, they need eliding from checkin and deleting at FlexMojos build-time if they exist.<br />
<pre class="brush:xml; toolbar:true"><plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<failOnError>false</failOnError>
<filesets>
<fileset>
<directory>${project.build.sourceDirectory}</directory>
<includes>
<include>FlexUnitApplication.mxml</include>
<include>FlexUnitApplication-app.xml</include>
<include>FlexUnitCompilerApplication.mxml</include>
</includes>
<followSymlinks>true</followSymlinks>
</fileset>
</filesets>
</configuration>
<executions>
<execution>
<id>remove FB FlexUnit-generated files</id>
<phase>initialize</phase>
<goals><goal>clean</goal></goals>
</execution>
</executions>
</plugin></pre>
Note this also works with adding extra source directories if:<br />
<ol>
<li>They don't need similar tidying</li>
<li>they're added in a later phase (e.g. <tt>generate-sources</tt>)<br />
</li>
</ol>
HTH!<br />
<br />
<b>UPDATE:</b> This may cause problems with clean since they will run this execution rather than the default. Can supply extra changes if people are interested.Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-41546385464118309592010-10-10T23:46:00.003+01:002011-04-22T13:22:12.652+01:00How to fix Flash Builder debugging after breakage by installing Flash Professional<span style="font-size: large;"><b>Short version:</b></span><br />
Flash Professional messed up Flash Builder's debugging capability. On Windows, one can replace references to the FP runtime from 'Professional with that to a FlashPlayerDebugger.exe and all will be well.<br />
<br />
<a name='more'></a><br />
<span style="font-size: large;"><b>Details:</b></span><br />
I've been using Flash Builder for the last year including its reasonable debugging capabilities.<br />
I had to install Flash Professional CS5 trial to work on something recently.<br />
When I returned to Flash Builder, debugging no longer worked -- it failed with the following error:<br />
<pre class="brush:text; gutter:false">C:\Program Files\Adobe\Adobe Flash CS5\Players\FlashPlayer.exe
Flash Builder cannot locate the required debugger version of Adobe Flash Player. You might need to install the debugger version of the Flash Player or reinstall Flash Builder. Do you want to try to debug with the current version?</pre>
<br />
Googling didn't find easy answer so thought I'd post my answer here.<br />
I'm on Windows so searched the registry for references and found these:<br />
<pre class="brush:text; gutter:false">HKEY_CLASSES_ROOT\FlashPlayer.AudioForFlashPlayer\shell\open\command
HKEY_CLASSES_ROOT\FlashPlayer.FlashVideo\shell\open\command
HKEY_CLASSES_ROOT\FlashPlayer.ProtectedMediaForFlashPlayer\shell\open\command
HKEY_CLASSES_ROOT\FlashPlayer.VideoForFlashPlayer\shell\open\command
HKEY_CLASSES_ROOT\ShockwaveFlash.ShockwaveFlash\shell\open\command
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FlashPlayer.AudioForFlashPlayer\shell\open\command
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FlashPlayer.FlashVideo\shell\open\command
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FlashPlayer.ProtectedMediaForFlashPlayer\shell\open\command
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FlashPlayer.VideoForFlashPlayer\shell\open\command
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ShockwaveFlash.ShockwaveFlash\shell\open\command</pre>
<br />
(I skipped those ending MuiCache)<br />
<br />
Switched one, didn't help. Switched more and restarted Flash Builder and all sorted.<br />
Changed from and to, respectively:<br />
<pre class="brush:text; gutter:false">"C:\Program Files\Adobe\Adobe Flash CS5\Players\FlashPlayer.exe" %1
"C:\Adobe\sdks\4.1.0.16076\runtimes\player\10.1\win\FlashPlayerDebugger.exe" %1</pre>
(all SDKs contain the FPD)Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-45049171740752486002010-01-05T16:27:00.008+00:002011-04-22T16:22:09.607+01:00RESTlet deployment woes (from GlassFish v2 to AppServer v2)Some <i>incomplete</i> notes on deploying our RESTlet-based application (tested on GlassFish) to our Sun AppServer v2.1.<br />
<a name='more'></a><br />
Deployed then had exception in the logs:<br />
<pre class="brush:text">PWC1382: Allocate exception for servlet Servlet java.lang.ExceptionInInitializerError
at org.restlet.Restlet.<init>(Restlet.java:99)
at org.restlet.Application.<init>(Application.java:147)
at org.restlet.Application.<init>(Application.java:134)
at com.maldenlabs.server.config.restlet.ConfigApplication.<init>(ConfigApplication.java:21)
at com.maldenlabs.server.config.restlet.ConfigApplication.<init>(ConfigApplication.java:17)
at com.maldenlabs.server.config.restlet.jee.Servlet.init(Servlet.java:34)
at javax.servlet.GenericServlet.init(GenericServlet.java:270)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:292)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:325)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:208)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:161)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1188)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:848)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:287)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:218)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:98)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:288)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:647)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:579)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:831)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
at com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106) Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission createClassLoader)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:594)
at java.lang.ClassLoader.<init>(ClassLoader.java:202)
at org.restlet.engine.util.EngineClassLoader.<init>(EngineClassLoader.java:55)
at org.restlet.engine.Engine.<clinit>(Engine.java:57) ... 46 more
</clinit></init></init></init></init></init></init></init></pre>
<br />
<b>Answer 1 found:</b><br />
<a href="http://forums.java.net/jive/message.jspa?messageID=215402#215402">http://forums.java.net/jive/message.jspa?messageID=215402#215402</a><br />
One needs to grant the "<span style="font-family: "Courier New",Courier,monospace;">createClassLoader</span>" permissions to the app in the domain's server.policy file.<br />
Specifically, to the file <code>/opt/SUNWappserver/domains/domain1/config/server.policy</code>, append:<br />
<pre class="brush:javascript; gutter:false">// Permissions for ConfigServer
grant codeBase "file:${com.sun.aas.instanceRoot}/applications/j2ee-apps/config" {
permission java.lang.RuntimePermission "createClassLoader";
};
</pre>
<br />
Restarting the instance, now see<br />
<pre class="brush:text">PWC1382: Allocate exception for servlet Servlet java.lang.NoClassDefFoundError: Could not initialize class org.restlet.engine.Engine
at org.restlet.Restlet.<init>(Restlet.java:99)
at org.restlet.Application.<init>(Application.java:147)
at org.restlet.Application.<init>(Application.java:134)
at com.maldenlabs.server.config.restlet.ConfigApplication.<init>(ConfigApplication.java:21)
at com.maldenlabs.server.config.restlet.ConfigApplication.<init>(ConfigApplication.java:17)
at com.maldenlabs.server.config.restlet.jee.Servlet.init(Servlet.java:34)
at javax.servlet.GenericServlet.init(GenericServlet.java:270)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:292)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:325)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:208)
at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:161)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1188)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:848)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:287)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:218)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:98)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:288)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:647)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:579)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:831)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
at com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
</init></init></init></init></init></pre>
<br />
<code>NoClassDefFoundError</code> = dependency problem (A cannot initialize because it uses B which cannot be loaded). My favourite explanation is <a href="http://jroller.com/sjivan/entry/difference_between_classnotfoundexception_and_noclassdeffounderror">here</a>. For us, <span style="font-family: "Courier New",Courier,monospace;">Restlet</span> is failing to construct (i.e. <span style="font-family: "Courier New",Courier,monospace;"><init></span>) because <span style="font-family: "Courier New",Courier,monospace;">Engine</span> is failing to load.<br />
<br />
For confirmation, built a test project with dependencies <code>Main.main -> ARequiresDepB.<init> -> BDependency</code>, ran from jar fine, removed <code>BDependency.class</code> from jar and re-ran:
<br />
<pre class="brush:text">Exception in thread "main" java.lang.NoClassDefFoundError: a/b/c/BDependency
at a.b.c.ARequiresDepB.<init>(ARequiresDepB.java:13)
at a.b.c.Main.main(Main.java:10)
Caused by: java.lang.ClassNotFoundException: a.b.c.BDependency
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 2 more</init></pre>
<br />
So the class named after NCDFE is the missing class that was required for the class named on the next line. (n.b. this constructor was setting into an instance variable.)<br />
Checking the EAR that contains the WAR, it contains the "<code>WEB-INF/lib</code>" that contains "<code>org.restlet.jar</code>" which contains "<code>org/restlet/engine/Engine.class</code>".<br />
Continuing to investigate...
<br />
<br />
<b>UPDATE:</b> I know we solved this. Sorry I never blogged it at the time :-(Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-9289201528857322322009-12-09T16:39:00.004+00:002009-12-17T13:03:01.919+00:00day off 9'th, BlazeDS, day off 11'th, networking 12'thDay off 2009/12/09.<br />
<br />
In the evening, ...<br />
<br />
JSON decoding caught me out by turning a property "<span style="font-family: "Courier New",Courier,monospace;">feeds.list</span>" into a member "<span style="font-family: "Courier New",Courier,monospace;">feeds.list</span>" -- rather reasonable on the face of it. Of course, this means one can only access via <span style="font-family: "Courier New",Courier,monospace;">object["feeds.list"]</span> (not <span style="font-family: "Courier New",Courier,monospace;">object.feeds.list</span>!)<br />
<br />
LiveCycle/BlazeDS<br />
Tutorial <a href="http://www.adobe.com/devnet/livecycle/articles/extend_webservices.html">Invoking web services using custom components</a><br />
N.b. Adding BlazeDS' Tomcat install to Eclipse doesn't start the Blaze samples -- guess something's not set.<br />
Realization: <span style="font-family: "Courier New",Courier,monospace;">useProxy</span> on <span style="font-family: "Courier New",Courier,monospace;">HTTPService</span> (etc) can only ever go to the server that the app was served from. <i>(While it would make some sense to allow alternative routing, Adobe don't appear to allow this.)</i><br />
<br />
Day off 2009/12/11.<br />
<br />
<a href="http://opensource.adobe.com/wiki/display/flexpmd/FlexPMD+Eclipse+plugin">FlexPMD Eclipse plugin</a> YakAxe!<br />
Cute port/reuse of [Java] <a href="http://pmd.sourceforge.net/">PMD</a> to Flex including an Eclipse (FlashBuilder) plugin.<br />
Installation notes:<br />
<ul><li>Eclipse plugin uses a set of Jar files supplied from a zip that one downloads separately then points to from Preferences.<br />
</li>
<li>Jars must be in a directory withoutspaces in the path.</li>
</ul>First installation and it doesn't appear to work. Watching videos for hints. More in later post.<br />
<br />
Saturday 2009/12/12<br />
Flex network classes -- there appears to be something of a progression:<br />
<ul><li>URLLoader = mentioned since it's used by HTTPService (and possibly WebService)<br />
Loads a URL, allows HTTP header overriding: most control, least web-service like = lowest level<br />
</li>
<li>HTTPService = REST</li>
<li>WebService = SOAP</li>
<li>RemoteObject = Call Java object methods in BlazeDS/LC*S via AMF<br />
</li>
<li>DataService = Call... ? (includes offline capabilities)<br />
</li>
</ul><br />
<ul></ul>Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-68821170659554952192009-12-07T23:55:00.003+00:002011-04-22T17:33:36.980+01:00Async FlexUnit 4 testingSo the <span style="font-family: "Courier New",Courier,monospace;">JSONCallHelper()</span> of the last post needs better testing.<br />
I gave it the following signature...<br />
<pre class="brush:as3; gutter:false">public static function JSONCall(urlQuery:String, responder:IResponder):void
</pre>
...but then went looking for how to test in FlexUnit 4.<br />
<a name='more'></a><span style="font-family: "Courier New",Courier,monospace;">addAsync()</span>(as mentioned <a href="http://cookbooks.adobe.com/post_How_to_handle_events_in_a_TestCase_-6882.html">here</a>) seems to be a FlexUnit 0.9 (as they call it) capability (due to not finding in a search of checked-out <a href="http://opensource.adobe.com/svn/opensource/flexunit/branches/4.x/">SVN workspace of FlexUnit 4</a>).<br />
<br />
There are a selection of <span style="font-family: "Courier New",Courier,monospace;">Async.*</span> methods listed <a href="http://opensource.adobe.com/wiki/display/flexunit/FlexUnit+4+feature+overview#FlexUnit4featureoverview-Async">here</a>. The obvious one seemed <span style="font-family: "Courier New",Courier,monospace;">Async.asyncResponder()</span> but using it seems to only hang my test-suite.<br />
<br />
Hmm, perhaps I might have misunderstood what <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/mx/rpc/AsyncResponder.html">AsyncResponder</a> is for.<br />
<br />
<br />
OK, debugger reveals it's actually my use of ILogger rather than Parsley's Logger class!<br />
I switched to the following (endeavouring to achieve similar behaviour to Parsley's within a project that doesn't link Parsley):<br />
<pre class="brush:as3; gutter:false">Log.getLogger(flash.utils.getQualifiedClassName(JSONCallHelper));
</pre>
...and the debugger revealed the following error was being hidden:<br />
<pre class="brush:text; gutter:false">Categories can not contain any of the following characters: []`~,!@#$%*^&()]{}+=|';?><./".
</pre>
For some reason FlexUnit lost the error / silently swallowed it, then hung rather than finishing its timeout on my async! Weird.<br />
Switched to using simple classname string, corrected URL under test and ...<br />
<br />
... now getting HTML not JSON despite wireshark showing I did supply the correct Accept header. Tomorrow.Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-40308314928945999592009-12-06T23:55:00.003+00:002011-04-22T17:32:24.205+01:00Flex HTTP header customization problems againSo, again I hit Flex's HTTP networking constraint -- <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/mx/rpc/http/HTTPService.html">HTTPService</a> rather than <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/URLRequest.html">URLRequest</a> this time.<br />
HTTPService does not seem to allow modification of certain headers, amongst them the "<span style="font-family: "Courier New",Courier,monospace;">Accept</span>" header (it was <span style="font-family: "Courier New",Courier,monospace;">"Cookie</span>" last time for URLRequest). Specific need: to call a RESTful webservice with "<span style="font-family: "Courier New",Courier,monospace;">application/json</span>" before "<span style="font-family: "Courier New",Courier,monospace;">text/html</span>" in the list (otherwise, I get back HTML!).<br />
<a name='more'></a><br />
<a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/URLRequestHeader.html">URLRequestHeader</a>'s documentation semi-explains about one only being able to change certain headers when in a certain sandbox/ApplicationDomain. Curiously, HTTPService doesn't mention -- just doesn't do!<br />
<br />
Ahha, thanks to good doc in <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/URLRequestHeader.html">URLRequestHeader</a> (the class that let me down for my "Cookie" need last time), I find <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/URLRequest.html">URLRequest</a> <i>does</i> support a "<span style="font-family: "Courier New",Courier,monospace;">requestHeader</span>" property. Perhaps there is light.<br />
<br />
<time passes...><br />
<br />
Yup, that seems to work. Switched from HTTPService to use of a <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/URLLoader.html">URLLoader</a> and things now behave. This brings the function size and scope up radically so time to refactor into a JSONCallHelper class (yes, possible name refactoring pending).<br />
<br />
An aside: I checked AdobeTed/Ted Patrick's FDOT library (<a href="http://onflash.org/ted/2009/08/fdot-making-hard-things-easier.php">here</a>, <a href="http://onflash.org/ted/2009/08/fdot-build-33.php">here</a> and <a href="http://github.com/adobeted/FDOT">here</a>) and it seems pretty similar goal -- albeit without the header specification but it looks reasonable to retrofit for an offered commit. Will puruse this slightly before then.<br />
<br />
Next, that my FlexUnit4 <span style="font-family: "Courier New",Courier,monospace;">Test(async,timeout=2000)</span> doesn't actually wait 2 seconds to see whether my method wants to do anything else. Reckon I must be misunderstanding its intent (or else those <span style="font-family: "Courier New",Courier,monospace;">Async.proceedOnEvent()</span> family of methods need using?!). <a href="http://www.insideria.com/2009/05/flashbuilder4-will-support-fle.html">This article's mention of proceedOnEvent()</a> indicates the answer -- one does need to call one of the Async methods so the framework knows (this <a href="http://cookbooks.adobe.com/post_How_to_handle_events_in_a_TestCase_-6882.html">recipe</a> also looked handy but might be out of date.) I ended up with the following kludge while still exposing the asynchronicity of the tested method:
<br />
<pre class="brush:as3"> const timer:Timer = new Timer(5000);
timer.start();
Async.proceedOnEvent(this, timer, TimerEvent.TIMER_COMPLETE, 8000, function(event:TimerEvent):void{
trace("timer done");
});</pre>
<br />
Well, looks like I've overcome it for now.Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0tag:blogger.com,1999:blog-8589804206549367883.post-88797426645104503222009-12-06T23:45:00.000+00:002009-12-08T12:35:53.173+00:00Eine kleine Yak musikAnother day, another blog.<br />
In conversation with a friend, I realised I needed somewhere else to be silly, let off steam and comment upon inanities, yaks vs. axes and other ... well, stuff.<br />
Let's see how we fare / fair :-)Arkadehttp://www.blogger.com/profile/03449987166922791728noreply@blogger.com0