Tuesday, December 30, 2014

<SELECT> with <OPTGROUP> doesn't have .remove() implemented [IE9+]

I found this semi-official link (because it's part of Microsoft.com, but a forum of sorts)

TL;DR - my way
var opts = selectControl.options;//I was doing other stuff with the options
opts[deleteIndex].parentElement.removeChild(opts[deleteIndex]);
 
The above was modified based on what was contributed by Abhisek Gupta:
selectControl.options[deleteIndex].parentElement.removeChild(selectControl.options[deleteIndex]); 
The explanation was something about .remove() not being in ECMAScript to begin with...

The root of the solution is to use .removeChild() but this one-liner is slightly more elegant:
  1. retrieve the HTMLOptionElement from its HTMLSelectElement;
  2. call its parent; in other words, our offending HTMLOptGroupElement;
  3. instruct for it to removeChild;
  4. pass in part 1. as argument to part 3.
You can alternatively check this other link.

Additionally, I wanted to detect for the presence of HTMLOptGroupElement. I added this to check:
function hasOptGroups(selObj) {
    if(selObj instanceof HTMLSelectElement) {
        var selCN = selObj.childNodes;
        if(selCN && selCN.length > 0) {
            for(var x=0;x<selCN.length;x++) {
                if(selCN[x] instanceof HTMLOptGroupElement) {
                    return true;
                    break;
                }
            }
        }
    }
    return false;
}



This way, I still get to use the original .remove() if there are no <OPTGROUP>'s present.

Monday, December 22, 2014

External Maxtor hard disk failed

I have a Maxtor OneTouch 1TB connected to my router as a NAS. So while trying to access it earlier, it couldn't be connected to successfully. The router browser UI showed the drive mounted but didn't show any read/write permissions like it used to.

I connected its USB to my laptop directly. Windows Explorer was able to display the drive (F: in my case here) but complained of the drive "File or directory is corrupted  or unreadable". My heart sank. Until I found this lifesaver. Most of the suggestions linked to shady blogs which I felt reluctant to try. Until I scrolled down to the solution suggested by kwagalamoshe.

Hello,

Try this 1

Click on Start --> Run --> Type cmd and press Enter.

"Command Prompt" will be opened.

Since you are having problem with G & H drivers, enter the below command

chkdsk /f g: --> Press Enter.

chkdsk /f h: --> Press Enter.

Good Luck 

It seemed straightforward enough, and it was utilising a system tool. No harm trying, so I decided to give it a shot. And it totally worked! CHKDSK was able to recover the filesystem with a couple of fixes to repair whatever was damaged.

I'm glad I found this solution but was surprised at the lack of information anywhere else. If you ever encounter anything similar, give CHKDSK a shot first (assuming you can still see the drive in Windows Explorer, hopefully). Good luck!

Thursday, December 18, 2014

Starhub TV and Fibre Termination

For the record, I called Starhub (1633) to ask what exactly do I have to return, if I want to cancel my Fibre Broadband and TV subscriptions.

The prompt reply:
  • Starhub Cable TV
    • Set-top box;
    • Power supply;
    • Remote;
    • and RCA cable (the one with the white-red-yellow connectors)
  • Starhub Fibre Broadband
    • Optical Network Terminal (likely Nucleus brand, white box);
    • Power supply;
    • and optic fibre cable (yellow, with green ends, connected to the wall terminal)
These items have to be brought to one of their Customer Service Centre outlets to be returned.

Tuesday, December 2, 2014

Select tab by its name to display as active for jQuery Tabs widget

There is a widget in the jQuery UI library known as "Tabs". Quite simply, it can be used to display tables in multiple tabs. I had the opportunity to figure out how to programmatically trigger a specific tab to be the currently active one to be displayed.

Here's what you need
  • the use of Active option
  • locating the tab by name like this
The HTML snippet is as follows:

<div id="tabs">

  <ul>
   <li><a href="#actionTab1"><span>One</span></a></li>
   <li><a href="#actionTab2"><span>Two</span></a></li>
   <li><a href="#actionTab3"><span>Three</span></a></li>
 </ul>
</div>
The script snippet is as follows:
<script>
//search tab index for value matching specific tab
var displayTab = $('#tabs a[href="#actionTab2"]').parent().index();
$("#tabs").tabs({active: displayTab});
</script>


In accommodating our server-side logic, a modification was done thus,

//variable set from server

var displayTab = $('#tabs a[href="#${svTab}"]').parent().index();

And because it may fail to find the item and return -1,

var displayTab = $('#tabs a[href="#actionTab2"]').parent().index();

if(displayTab == -1) {
  displayTab = 0; //default to first tab
}


"A negative value selects panels going backward from the last panel."

The final version I used:

<script>
//search tab index for value matching specific tab
var displayTab = $('#tabs a[href="#${svTab}"]').parent().index(); 

if(displayTab == -1) {
  displayTab = 0; //default to first tab
}
$("#tabs").tabs({active: displayTab});

</script>

In short:
  1. Identify the <div> of the tab heading,
  2. Filter for its <a> children with the matching href attribute,
  3. Return the (zero-based) index of the parent <li>
  4. Create a JSON object setting the index into the name "active"
  5. Call the widget with the JSON object as the argument
It is possible to simply call Tabs with {active: 1} but I felt that it was more readable to be able to search and set the index value according to the tab name instead, so that it can work even if the tab items get rearranged.

And that was it. Have fun!

Monday, October 27, 2014

How to burn your weekend, with jackson-mapper

TL;DR - version 1.5.3 in pom.xml was wrong; changing to 1.9.10 fixed it.

We are still knee-deep past our project deadlines. There we were, generating the EAR file to be deployed on to our HSM-laden servers in office. Introduce my version. I'd been mucking around happily developing my own stuff. Now comes my turn to deploy my version merged from CVS into the JBoss. I'll just cut it short to say that, other than my version, nobody else could get a specific ajax function to operate properly.

The team became stuck for a day or two. Washing my hands off of it, "it was working when I left", and several hours later, they still couldn't get the clean CVS copy to do the job. None of their EAR files could. Then Saturday late night comes, and a colleague decides to head back to office after dinner. I joined her remotely from home. She mucked around for a good 2 hours. Still no dice. Then she decided to drop my webapp WAR into her EAR. It works! She diff'd the archive contents in BeyondCompare, and found several differences. We tested out several theories, but to no avail. It was around 2.30am when we pretty much decided to give it a rest.

Before she left, she noted one difference for me to investigate, since I was planning to head down this morning. The /lib files contained 2 different pairs of JAR files. Both jackson-mapper and jackson-core JARs represented themselves differently in her WAR and mine.

After researching, it turns out jackson-mapper has a dependency on jackson-core, meaning they should always come in pairs. I had both pairs of version 1.5.3 and 1.9.10 in my WAR.

Come morning, I was in the office testing out this newfound theory. In order not to let my miraculous EAR interfere, I only meddled with a copy of the EAR left behind for me by my colleague.
  1. Control test - deploy her original, untainted EAR; true to form, the ajax call is broken.
  2. Replace both jackson-mapper and jackson-core with v1.9.10 inside WAR; hurray, it works!
  3. Additionally, due to extra instructions with another colleague, remove jackson-core and leaving solely jackson-mapper v1.9.10 within; expectedly, it doesn't work. His impression was our pom only indicating the use of the mapper JAR and not the core JAR, so maven truly did its job behind the scenes by including the required dependency without us even realising.
After some hemming and hawing because this guy is reluctant to upgrade from 1.5.3 to 1.9.10, in case it breaks anything else, I barely persuaded him to go ahead with it anyway or it'd remain a showstopper.

Our pom was indicating 1.5.3 all this while, because nobody wants to rock the boat with a new version since it works. Even though v1.5.3 is 4 years old and 1.9.10 is 2 years old at best. The version number in our pom for jackson-mapper was updated, so that the maven on everybody's machines would know to use the newer version instead.

Was it that hard to identify the problem? The server never provided any feedback in our logs. The ajax function obviously did its job, since the database was updated because of it. But with v1.5.3, the result never returned to the browser. The culprit could either be due to the @ResponseBody implementation being unavailable in 1.5.3 (unlikely), or the fact that the ajax call was using the jQuery implementation on a POST method instead of GET. We don't have time to point any more fingers.

The problem with the multitudes of libraries and frameworks available, is that through such obfuscation, identifying problems like this can become increasing difficult. And not forgetting the convenience of the Spring framework that performs autowiring with annotations. Those files compile fine and are happily packaged into WARs, JARs and EARs. Except they'd quietly fail at runtime.

Our project continues on its way with our testers picking out the bugs.

Friday, October 17, 2014

Loading DLL in a web-based applet

This is going to be lengthy and technical.

The problem
My project has a page that calls an applet that in turn loads a DLL to perform certain tasks. This works when the page is first loaded, but dies when the page refreshes itself. Log traces indicate that the applet dies when calling the System.loadLibrary with the DLL after the first time. Suspicions rose at the inner workings of either the applet jar in browser cache, garbage collection, or DLL being loaded. My debug research went both ways.

Caching applet.jar in browser
The search started with me locating the various mechanisms used to flag to the browser that the applet is not to be cached. I found out about cache_option and cache_archive pair. I revisited the legacy_lifecycle switch. I'd even attempted to switch over to the "recommended" method of using deployJava.js in place of my <applet> tag. Fortunately and unfortunately, I found out that the jsession variable was already appending to the applet.jar?jsession= due to the framework in place, so that was a dead-end. It still didn't work.

Garbage Collection
Attempts were made to explicitly call System.gc() in the applet stop() and destroy() methods. The class for loading the DLL was set to null prior. Doesn't work.

System.loadLibrary calling of the DLL
Turning my attention to the DLL loading mechanism, I ventured to unload the DLL. The standard pattern was to make use of a static call to System.loadLibrary in a Java class. What could possibly have gone wrong? I found out that people suggested to unload the DLL because they have a need for it. Following their words, I crafted my custom ClassLoader.

My project was a web application. The applet is stored within a jar, hosted on the web server. The custom ClassLoader has to be able to access the http:// URI scheme, read the jar file and dump out the class file from within. I improvised by combining the solutions from here, here and here.

MyCustomClassLoader:
public class MyCustomClassLoader extends ClassLoader {
    private String MyCustomAppletUrl;
    /**
     * The HashMap where the classes will be cached
     */
    private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();

    public MyCustomClassLoader(String url) {
        this.MyCustomAppletUrl = url;
    }

    @Override
    public String toString() {
        return MyCustomClassLoader.class.getName();
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        if (classes.containsKey(name)) {
            return classes.get(name);
        }

        byte[] classData;

        try {
            classData = loadClassData(name);
        } catch (IOException | URISyntaxException e) {
            throw new ClassNotFoundException("Class [" + name + "] could not be found at " + new File(name).getAbsolutePath(), e);
        }

        Class<?> c = defineClass(name, classData, 0, classData.length);
        resolveClass(c);
        classes.put(name, c);

        return c;
    }
   
    private byte[] loadClassData(String name) throws IOException, URISyntaxException {
        URL url = new URL(MyCustomAppletUrl);
        BufferedInputStream in = new BufferedInputStream(url.openStream());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int i;

        while ((i = in.read()) != -1) {
            out.write(i);
        }

        in.close();
        byte[] jarBytes = out.toByteArray();
        out.close();
       
        JarInputStream jis = new JarInputStream(new ByteArrayInputStream(jarBytes));
        JarEntry entry;
        InputStream inStream = null;
        while ((entry = jis.getNextJarEntry()) != null) {
            if (entry.getName().equals(name.replace(".", "/") + ".class")) {
                inStream = jis;
                break;
            }
        }
       
        if(inStream != null) {
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            int nextValue = inStream.read(); 
            while (-1 != nextValue) { 
                byteStream.write(nextValue); 
                nextValue = inStream.read(); 
            }
           
            byte[] classData = byteStream.toByteArray();
            out.close();
            return classData;
        }
        return null;
    }
}


MyCustomLibraryLoader:
public class MyCustomLibraryLoader {
    private Class<?> MyCustomClass;
    private Object MyCustomClassObj;
   
    public MyCustomLibraryLoader(String url) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        MyCustomClassLoader cl = new MyCustomClassLoader(url);
        MyCustomClass = cl.findClass("com.nec.asia.MyCustom.client.MyCustom_Client");
        MyCustomClassObj = MyCustomClass.newInstance();
    }
   
    public String MyCustomClientAction(String inputXML) {
        System.out.println("MyCustomClientAction:");
        Method m;
        try {
            m = MyCustomClass.getMethod("MyCustom_Client_Action", String.class);
            return (String) m.invoke(MyCustomClassObj, inputXML);
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        return null;
    }
   
    public String MyCustomVerifyView(String inputXML) {
        System.out.println("MyCustomVerifyView:");
        Method m;
        try {
            m = MyCustomClass.getMethod("MyCustom_VerifyView", String.class);
            return (String) m.invoke(MyCustomClassObj, inputXML);
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        return null;
    }
}

And guess what? It didn't work. I meant that I managed to use them to retrieve the remote jar, extract the class and load the DLL, but my original problem remained. Reviewing another product with a similar setup proved vital, and had me deleting the above files.

The solution
Yes I had it working in the end. The class file with the native method calls was placed in a separate jar all by its lonely little self. This second jar was then added to the archive param in the applet:
<param name="archive" value="mywebapp-applet.jar,lonely-dll-caller.jar" />

And the applet behaved like my drama was totally uncalled for. Other stuff I decided to keep for now:
  • the legacy_lifecycle parameter
  • use of <applet> instead of <object> or even use deployJava.js
  • don't forget to include 
    • <param name="type" value="application/x-java-applet;" />
    • <param name="scriptable" value="true" />
    • <param name="mayscript" value="true" />
That's all folks! The applet loads the DLL process properly now, even after subsequent reloading of the same page.

Thursday, October 9, 2014

20 steps to Java/DLL integration over JNI

I'm not well-versed in C++ nor .Net, so I was still learning as I encountered this at work. While not being overly generic yet not too specific about the ordeal I encountered, it involved getting a DLL to work with our Java components. Sounds straightforward enough? It was... kind of. Guy 1 is in charge of developing the main DLL and its compilation stuff. Guy 2 is versed in C++ but understands Java sufficiently to provide the DLL for the Java Native Interface (JNI) adapter to the main DLL from Guy 1, along with basic testing classes in Java.

It certainly looked like he had already done all my work for me. Not quite. I'd have to proceed with his setup to get their bits working with the rest of our web application in a Java framework. Here's how it went... (WARNING: wall of text that includes technical stuff and bitching)

TL;DR - integrated Java with DLL using JNI, shenanigans with co-workers ensue, Java calls to DLL success.

Step 1: Setup the DLL paths and environment provided by Guy 2 in my Eclipse,

Step 2: Realise Guy 2 provided basic XML parsing via DocumentBuilder,

Step 3: Convert everything he's done into XStream-friendly POJO,

Step 4: Realise XStream is an external library and commence search for alternative to reduce additional footprint,

Step 5: Took the advice of Blaise Doughan and adopted Java Architecture for XML Binding (JAXB) because it's part of the javax.xml.bind package,

Step 6: Discovered the joys of source annotations and XML adapters,

Step 7: Realise that the XML definition that was long decided before I was brought on board (and already implemented on the .Net server side) is complicated (e.g.:
<fans>
  <fan type="standing"/>
  <fan type="desk"/>
  <fan type="celebrity"/>
</fans>
) by attribute naming that prevented JAXB from unmarshalling the String to object,

Step 8: Came up with my own convoluted (I swear it's as elegant as I could get it) solution to first read the <fans> to determine what types were in the list provided, before manually stripping <fans> from the String front and back and running it through JAXB another time, (if you have a better way, let me know!)

Step 9: Attempt to run the whole shebang with the DLL,

Step 10: Act surprised that JNI complained of an UnsatisfiedLinkError for the DLL,

Step 11: Figured that Eclipse had to be told where to look with -Djava.library.path="C:/that_dumb_place/Dlls" when running my test program,

Step 12: Nope still won't work, spend the morning poking around some more before giving up and asking Guy 2 if I'd missed out anything,

Step 13: Guy 2 refers me to Guy 1 for the DLL portion, "fair enough" I lied to myself,

Step 14: Decided I should test further without the Java components by first running the .exe test program they provided... crashed,

Step 15: Approach Guy 1 who tells me he'd investigate the error on his end first, while I proceed to lunch,

Step 16: Guy 1 returns to offer me his solution of running his test program on his spare laptop that's been configured to work bug-free, instead of my problematic laptop that's long been tainted with other muck from previous projects,

Step 17: "Does this thing have Java installed?", I queried. Guy 1immediately forbids me from running my codes on his precious laptop. Explained to him I needed to run my codes with his because I had to integrate them for this project. Seeing there was no other way to squirm out of this, he promptly took over my laptop to figure out how to get his test program running,

Step 18: I twirled around in my chair for almost 2 hours before he returned triumphant. It worked! At last, his test program works on my laptop. He had installed a new driver that goes along with a new model of the Human-Interface Device (HID) that we have already provided the client.

Step 19: Indeed, System.load("That_Darn_JNI") works with the DLL from Guy 2 in his codes that I've since adopted and turned it from a baby into an adolescent, complete with full-blown set of beans and action classes, just as long Eclipse knows about that -Djava.library.path it cleverly denies knowing about,

Step 20: Try running my test program. Nope, Unsatisfied remains. Made comparison between JNI DLL and existing known working DLL from another product, and finally getting around to rectify minor bugs in my codes to marshal/unmarshal between the XML and POJO.

So I finally got what I wanted... well almost. The following addendum is the cherry missing from my cake...

Step 21: Realised that because I'd shifted the DLL away from the original XYZ.Product package into my Java-convention style of com.XYZ.asia.product.client caused the JNI to not map to the native DLL, and that it'd be confusing to leave the product package as XYZ.Product while the rest of the project is differently identified,

Step 22: Ask Guy 2 about the JNI, he patiently explained about how the header works but ultimately suggested that I should talk to Guy 1,

Step 23: Locate Guy 1 about passing him the JNI header to generate the DLL for me. Nope, his bunch of codes would take him way longer to generate the resulting DLL,

Step 24: Return to Guy 2 about it. He relents, and I generate the JNI header via javah.exe mapping to the relocated JNI wrapper

Step 25: I have yet to test this new DLL yet, although I reckon it should function as expected... and hopefully this tiring liaison with them is over for the time being...

And thus, at the end of the day, I got my DLL the way I wanted it, the HID works on my machine, the client-server calls are working and I'm getting the XML strings parsed correctly into Java objects. It's been gruelling, but educational.

To be continued...

Saturday, January 18, 2014

Android ShareActionProvider does not provide share action without shareHistoryFileName set

TL;DR - It is compulsory to call setShareHistoryFileName() after initialising from getActionProvider().


I was trying to call the ShareActionProvider from a Contextual Action Bar. As it turned out, after trying to figure out why it didn't work on my Jelly Bean emulator, I found this issue that has had hardly any attention on it. Running the built-in ApiDemo (for API 10, on both the emulator and my actual device) proved that it really doesn't have anything catered for this action. Bottomline is, I had to switch to plugging in my own phone to test my change for this bit.

When the documentation mentioned "Defaults to DEFAULT_SHARE_HISTORY_FILE_NAME." my assumption was that I did not need to even call setShareHistoryFileName() since it's already set with that as default. Why shouldn't it? And without which, my share action fails to react, even when the icon is sitting nicely on the screen.

I only managed to find people asking how to disable the share history, but not this other bit. I don't really care for the share history in this case, but getting it to work without which seems impossible. Dear people at Google, maybe would you like to consider either stating that setShareHistoryFileName() must be called, to pass in the DEFAULT_SHARE_HISTORY_FILE_NAME, or maybe just plain set it in by default or to null if it was never set? Isn't that what built-in defaults are for?

Even though I know there are tons of codes floating around that's basically similar every which way, here's a snippet of my codes for posterity:
private ActionMode.Callback actionModeCallBack = new ActionMode.Callback() { ...
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.confirmed_context_menu, menu);
           
            shareAction = (ShareActionProvider) menu.findItem(R.id.share_confirmed).getActionProvider();
            shareAction.setShareHistoryFileName(ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME);
            shareAction.setShareIntent(createShareIntent());
            return true;
        }
 I must qualify my lack of understanding was specifically for this bit of use for the ShareActionProvider in a contextual action bar that appears only after a long-press, but no where did I spot anybody mentioning that they succeeded in calling the Provider without setting the share history... or is everyone just copying the codes from documentation line-for-line?

Friday, January 17, 2014

Closing the Contextual Action Bar when switching to another Fragment

Been playing around in Android in my spare time when I encountered this... I have 3 Fragments listed in tab mode on the action bar:
  1. Fragment #3 is displayed, and has a contextual action bar shown from a long-press.
  2. Selecting Fragment #2 brings me to the page, but with the contextual action bar left over from Fragment #3.
 Clearly at this stage, I'd want the contextual action bar gone, but the results from Google were inconclusive. Fortunately, a bit of random checking in the documentation turned up onDestroy() in the Fragment class. There were hints and speculation suggesting the use of hide()/finish()/invalidate() and possibly applying them in the main Activity, from StackOverflow but I didn't find them exactly useful to my situation.

By chance, I decided to give one combination a shot, gave it a whirl and it seems to be working for me. It's surprisingly straightforward.

Here's my actionMode and its callBack:
    private ActionMode actionMode = null;
    private ActionMode.Callback actionModeCallBack = new ActionMode.Callback() {
       
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }
       
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            try {
                for(int i=0;i<getListView().getCount();i++) {
                    getListView().setItemChecked(i, false);
                }
                updateHighlightsOnChecked();
                getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
            } catch(IllegalStateException e) {
                Log.d(app_name_tag, "ConfirmedFragment.actionModeCallBack.onDestroyActionMode IllegalStateException");
            }
            mode = null;
        }
       
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.confirmed_context_menu, menu);
            return true;
        }
       
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            List<Integer> itemPositionList = new ArrayList<Integer>();
            Log.d(app_name_tag, "checked items: " + getListView().getCheckedItemCount());
            SparseBooleanArray bArr = getListView().getCheckedItemPositions();
            if(bArr != null) {
                for(int i=0;i<getListView().getCount();i++) {
                    if(bArr.get(i)) {
                        itemPositionList.add(i);
                    }
                }
            }
           
            switch(item.getItemId()) {
                case R.id.remove_confirmed:
                    callback.onConfirmedOrderRemoved(itemPositionList);
                    updateOrderList();
                    mode.finish();
                    return true;
            }
           
            return false;
        }
    };

The actionMode gets initiated in the long-click listener:
@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
       
        getListView().setOnItemLongClickListener(new OnItemLongClickListener() {
           
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
                getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
                getListView().setItemChecked(position, true);
                updateHighlightsOnChecked();
                actionMode = getActivity().startActionMode(actionModeCallBack);
                view.setSelected(true);
                return true;
            }
        });
    }

And lastly, the most important part:

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(actionMode != null)
            actionMode.finish();
    }

I figured since the contextual action bar (or pretty much everything else) would be wiped when the fragment gets swapped out, it can give the actionMode a holler to finish its business.

Give it a try and let me know if it works out for you.