Tech Blogging


Android, Troubleshooting "W/View: couldn't find view with id"

posted Sep 5, 2017, 5:27 AM by Haris Hashim   [ updated Sep 5, 2017, 5:31 AM ]

It is not easy to troubleshoot this error without knowing why it happens! 

Error message and debug point

Eyeballing above message also does not help much! ;)

To cut a long story short, in layout xml file we declare widgets like bellow:


<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="32dp"
android:layout_marginTop="23dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/editText"
android:layout_below="@+id/editText"
android:layout_marginTop="16dp"
android:text="Button" />

Id of EditText is set using "@+id/editText"

It is used again later as "@+id/editText" when Button is positioned bellow and aligned to end of EditText.

The way "@+id"  work is that it will try to find existing id with editText label. If it is not found, new random id number is given. This kinda explain why "@+id" is used for both case of creating a new id for widget and also to refer to existing widget.

Here is a shocker. We can also do this instead of using "@+id"

android:layout_alignEnd="@id/editText"
android:layout_below="@id/editText"
So what is the different between using "@+id" and "@id"? 

Unlike the previous form, "@id" will throw compile error when existing id is not found. Layout_alignEnd and layout_bellow depend on widget with id to exist to do the relative positioning, right? And the id can not just be some newly created random id. 

When using "@+id", Android will give us this message during runtime:

"W/View: couldn't find view with id xxxxxxxxx"

Hence the hard to troubleshoot problem. Another thing is that, not all line with "@+id" is the one having problem. 

In my case, I did the following to troubleshoot.

1. Find all line in xml layout file that have "@+id" but not "id="@+id". On Windows this is done using Notepad++ find in file function with regex search keyword. The keyword is "[^id]="@\+id" (refer to picture). 

Find in files using regex

Not being an expert in regex, regexr.com website help me a lot in testing and getting the right expression.

2. Change "@+id" to "@id" and rebuild the project until the one that give compile error is found. Much of this is try an error approach.

Error found


From that troubleshooting, I found the problem to be order of widget declared in xml file when using relative layout. Fix that and problem is solved! 

Happy troubleshooting!

RecycleVew Adapter Show Wrong Data When Scrolling

posted Sep 3, 2017, 1:44 AM by Haris Hashim   [ updated Sep 3, 2017, 6:09 AM ]

Introduction

This is also a good code sample for RecyclerView within another RecyclerView. Get the code in GitHub!

When developing Android app using RecyclerView, common problem is to have wrong data displayed after scrolling. The reason is because RecyclerView reuse previous RecyclerView widget to show next data after scrolling. 

Quick Fix

This problem can be quite hard to debug. So a quick and dirty solution is to disable the reuse or recycling function. Of course, this is a temporary solution or a workaround until real issue is discovered and fixed.

How to do that? Just set the ViewHolder setIsRecyclable to false in onBindViewHolder. As per bellow code snippet:
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final ContentItem content = values.get(position);
holder.txtName.setText(content.getName());
holder.txtHeader.setText(content.getDescription());
holder.txtFooter.setText("Footer text is here!");

holder.setIsRecyclable(false);

vAdapter = new VariantAdapter(content.getVariants());
vRecyclerView.setAdapter(vAdapter);
}

Fixing the Real Problem

It turns out the real problem is RecyclerView should be declared inside ViewHolder rather than in the Adapter class. As per bellow code snippet:
public class ViewHolder extends RecyclerView.ViewHolder {
// ... codes redacted

private RecyclerView variantRecyclerView;

public ViewHolder(View v) {
super(v);
// ... codes redacted
variantRecyclerView = (RecyclerView) v.findViewById(R.id.variant_recycler_view);
}
}

The rest of the code is in the Adapter onBindViewHolder as bellow snippet:

    @Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// ... codes redacted
variantLayoutManager = new LinearLayoutManager(holder.view.getContext());
holder.variantRecyclerView.setLayoutManager(variantLayoutManager);
variantAdapter = new VariantAdapter(content.getVariants());
holder.variantRecyclerView.setAdapter(variantAdapter);
}

After implementing the above code, it is save to remove code that disable reuse/recycle function in previous section.

You can view and try the entire test code in GitHub. Master branch contains the fixed code while not-fixed branch is otherwise for testing and reproducing the error. 

Android and Dagger 2 in 5 minutes!

posted Aug 12, 2017, 12:59 AM by Haris Hashim   [ updated Aug 12, 2017, 1:27 AM ]


Introduction

Dagger 2 for Android can be unnecessarily complicated. Here is a tutorial for simplified usage of Dagger 2 as well as adding "quickstart" code as Android Studio Live Template.

Steps

Use Android Studio to create a new project.


Create new android project

Just click next and accept all the default option. Just make sure that it targets phone and tablet and MainActivity class is created by the wizard.

Add Dagger 2 dependency to gradle app module.

Add force resolution strategy


Add the following code as per above picture. These codes might not bee needed so feel free to try without it.

    
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}

And the needed dependency as per bellow picture.  

Add dagger dependencies


Use bellow codes to copy paste.

compile 'com.google.dagger:dagger:2.11'
compile 'com.google.dagger:dagger-android:2.11'
compile 'com.google.dagger:dagger-android-support:2.11'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'


Add quick start code to Live Templates

Use the file menu to open Settings => Editor => Live Templates

Life Template

Select "user" and add a new user Live Template as per bellow image. Set Abbreviation to something easily remembered. This example use "DA" as the shortcut, so that you can type DA and press TAB key to generate the code.

Create User Live Template

Use bellow code as the template by copy and paste into Template text.

public class App extends Application implements HasActivityInjector {

@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

@Override
public void onCreate() {
super.onCreate();
DaggerAppComponent.create().inject(this);
}

@Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}

//Move this interface to its own class file and do Build => Make Project
@Component(modules = { AndroidInjectionModule.class, AppModule.class})
public interface AppComponent extends AndroidInjector<App> {
}

@Module
public abstract class AppModule {
@ContributesAndroidInjector
abstract MainActivity mainActivity();
}
}


Create App Class and Set the Manifest

Add a class that extend Application class. This can be done by right clicking the application package and use context menu to add a new Java class. Refer to bellow pictures.

Right click on application package

Name the class App and superclass to be android.app.Application.

Add App class

Set the class as application class for the project app module.

Set the app in manifest

Use Live Template to Add Boilerplate Codes

Open the App class so that we can add codes saved earlier as Live Template. Just delete bellow code.



public class App extends Application {
}

Type abbreviation that we set previously; in this case DA and press TAB on the keyboard. You should get the code as bellow picture.

Generate Live Template code and resolve missing import

As in above picture, blue box will popup to resolve missing import. Just press ALT + ENTER until they are all resolved.

However DaggerAppComponent (line 14 in the picture) will not resolve. Dagger has to generate DaggerAppComponent class. For this to happen we need to move AppComponent interface to its own file.

To do this cut bellow codes from your App class.


//Move this interface to its own class file and do Build => Make Project
@Component(modules = {AndroidInjectionModule.class, AppModule.class})
public interface AppComponent extends AndroidInjector<App> {
}

Create a new interface and name it AppComponent. We will not need AppComponent code generated in this file. Simply delete and paste code that we cut in above step.

Use keyboard shortcut  CTRL+F9 to make the project. After make is completed, DaggerAppComponent in App class should be successfully resolved.

Create a TestService Class and Inject it to MainActivity for testing.

Use bellow code for TestService class. Take note of the @Inject decoration usage. TestService constructor will be called when it is injected into MainActivity class.



public class TestService {

private TestUser user;

@Inject
public TestService(){
user = new TestUser();
user.setName("Test User");
user.setEmail("test@user.com");
}

public TestUser getUser() {
return user;
}

public class TestUser {
private String name;

private String email;


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}
}
}

Ensure that MainActivity layout file have the following TextView widget


<TextView
android:id="@+id/text_hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />

And implement codes as in bellow picture in exact order as highlighted.

Main activity code

Bellow codes for copy paste.


public class MainActivity extends AppCompatActivity {

@Inject TestService testService;

@Override
protected void onCreate(Bundle savedInstanceState) {

AndroidInjection.inject(this);

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView textHello = (TextView)findViewById(R.id.text_hello);
if(testService != null){
textHello.setText("SUCCESS! User is " + testService.getUser().getName() +
" and email is " + testService.getUser().getEmail());
}else{
textHello.setText("FAILURE!");
}

}
}


If everything is done correctly, we will see bellow screenshot when the app is run.

Success screenshot


Conclusion

It takes 5 minutes or less to start using Dagger 2 when utilizing Android Studio Live Template functionality.

Much faster to just clone the code from https://github.com/HarisHashim/QuickDagger ;) . 

Thanks for reading and have fun!

All com.android.support Libraries Must Use the Exact Same Version

posted Jul 31, 2017, 8:40 AM by Haris Hashim   [ updated Jul 31, 2017, 8:16 PM ]



Recently I have encountered this warning in Android Studio build.gradle. 


All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes).


"All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes)."

The next line in the error give some hints.

"Found versions 25.3.1, 23.1.1. Examples include com.android.support:animated-vector-drawable:25.3.1 and com.android.support:recyclerview-v7:23.1.1"

It is not a show stopper since the project build just fine and did not crash. But after few project having same error, it annoys me enough to investigate and fix.

Troubleshooting

Open cmd shell, change directory to project root folder and execute bellow gradle command.


gradlew -q dependencies app:dependencies --configuration compile

It will list all dependencies and sub dependencies. The problem is that this project depend on dependency that in turn depend on different support libraries version. Knowing that the project depends on support library 25.3.1 and hint is given that version 25.3.1 and 23.1.1 is found. So the culprit must be a dependency that make use of version 23.1.1. Search or eyeball for such dependency in the list.


Troubleshooting and finding the root cause


Base on above picture, we need to do something about secretsauce component that depends on support library version 23.1.1.

In this particular case, since secretsauce is an opensource library. My quick and easy solution is to add it as part of the project and rebuild it with newer version of support library. 

Add the Library

Download the code from github as zip. Copy the secretsauce sub folder as in bellow picture into project root folder.


Add secretsauce as library in the project


Add secretsauce into the project by changing project settings.gradle to include the library.


Change project settings.gradle
 

The library is now integrated into the project and we can use "compile project(':SecretSauce')" in app module build.gradle file. Don't forget to comment out the old secretsauce dependency.

 
Add librart into app module gradle.build and comment out old dependency

Change the Version Number

Modify secretsauce module build.gradle to change support library version number.


Chang support library version number


Sync and build the project. Fix any errors encountered.

Code in Github

Here is a sample project in github as demonstration of the final and working result. Have fun!


Feel free to message me in GitHub if there is question!

Testing Paypal PayNow Button in Sandbox

posted Mar 24, 2015, 3:02 AM by Haris Hashim   [ updated Mar 29, 2015, 7:42 PM ]

PayPal Rocks

Introduction


Today, while testing Paypal PayNow button, I discovered that even Paypal can screw up. !FacePalm! Half of my day down the drain. But after some googling and tips from stackoverflow, things got right back on track. Finger cross!

If Paypal, a big company handling lots of money can do this. I should cut my self some slack too. But in your case, dear reader, I am going to cut you some tips so that you wont stumble into similar  pitfall.

Rocking Multiple Paypal Website

I am going to list some and give some explanation. 
  1. The main website : www.paypal.com or www.paypal.com.my.
    • Either of both are the main website where you can log in and do stuff with your PayPal account and funds. 
    • If you are Malaysian and accessing PayPal from Malaysia, you will get the .my domain.
  2. Paypal website for Developer developer.paypal.com
    • This website have lots of stuff for developer. It can be confusing. However when doing sandbox testing click "Dashboard" in the main menu at the top of the site. It will open a new page. Look for "Sandbox" on the left side meny and click "Account" just bellow it.
    • As for logging in. I usually perform sign in using the main website (i.e. www.paypal.com) and then open up the developer web site. The credential is carried over. No need to sign in twice. IMHO, this is a little bit safer against wrongly typed URL.
  3.  Paypal sandbox website : sandbox.paypal.com or www.sandbox.paypal.com (yup there is such thing as www.xxx.yyy.zzz)
    • This sandbox website are equivalent to the main website. Just that it is the sandbox environment for testing. For instant a buyer account can get $ 9999 money in whatever currency. Any transaction here will not impact the real account.
    • If you are testing Paypal sandbox, make sure everything is done under this sandbox website. It pays to do a quick glance on the browser URL box at each step. This is important.
In point 3, I mentioned buyer account. To do sandbox testing, business and buyer account need to be created using Developer website mentioned in point 2. In my case, two accounts were already there (1) mydomain-facilitator@mydomain.com and (2) mydomain-buyer@mydomain.com. 

The idea is that a facilitator account, which is a business account will create a BuyNow button and then embed this button somewhere. In my case, even a local html page will work. Clicking that button should open up PayPal sandbox site with order details. A buyer account, which is a personal account, can then sign in and proceed with payment in sandbox environment.

In short, the flow will be 
  1. Sign in to Paypal main website.
  2. Sign in to Paypal website for developer and create facilitator and buyer account. Or in my case use pre-created accounts.
  3. Sign in to PayPal sandbox website as facilitator and create the BuyNow button. Don't forget to sign out after, to avoid confusion between facilitator and buyer account.
  4. Embed the BuyNow button in a page somewhere and click on it.
  5. In the opened sandbox order detail page, sign in as buyer user and proceed to pay.
Sounds east right?

Pitfalls That Rock Me Instead

I forgot the exact step, but at least I remember these small and big rocks that PayPal throw in my general direction. Was very busy ducking those rocks to remember. Sigh!
  1.  Multiple websites opened at the same time in same browser means credential are mixed a lot. To avoid this, best to open main website and developer website in one browser (for instance Chrome) while opening sandbox website on another browser (for instance Firefox).
  2. This is where PayPal screwed up. Apparently there is bug in the sandbox environment. To create BuyNow button, facilitator need to sign in to the sandbox website and click "Merchant Services" on the top menu. This link is broken. Doing this on the same browser where I sign in as the real account (instead of a test account) cause me to create and test real BuyNow button. Take me few hours to realize that buyer account can not sign and credit card was rejected because of this (thanks a bunch PayPal). To avoid this pitfall, in addition to point 1 above, always make sure that sandbox is in the URL at every step of testing.
  3. Take note that if tips in point 1 is followed and clicking "Merchant Services" in point 2 above is performed, a white page with bunch of cryptic error is displayed. At least no harm is done, but still a show stopper. What works for me (based on this StackOverflow, first answer) is to open up "Merchant Services" link in the other browser with my real PayPal business account. Copy the URL, paste it in the browser with sandbox environment and the facilitator already signed in and change the main website URL to a sandbox URL. Phew!
  4. Phew (repeat for dramatic effect) and still does not work! So here is the big rock. Or at least for today and for some cosmic reason might be something that only applicable to me. I really have no idea why something like this happened. Change the URL from using HTTPS to HTTP. Mysteriously, you have to make sure the URL is not in the form of "www.sandbox" by removing "www". 
  5. Point 4 will only work if you accept a cert intended for "www.sandbox.paypal.com" because step 4 will browse to "sandbox.com" and the cert was not intended for it. This is scarry, I shouldn't be asked to do this inview of all HTTPS security loophole news recently.
Avoiding and getting around above pitfalls allow me to create that much needed BuyNow button. The rest of testing still present some challenge for me. Perhaps they are story for another days. However, good to know that at least I am able to test purchase using BuyNow button using with buyer user signed in. Alternative to that is to buy using credit card information of buyer user without signing in.

In Conclusion

I guess, pitfalls above just highlight how hard to make good bug free software/system nowadays. Knowing that even PayPal have bugs. But my guess and to end this blog in a more positive tone.

To err is human, to forgive is DEVELOPER.

Comments & Feedbacks

The gadget spec URL could not be found


OpenShift DIY Cartridge and JRuby + Gem Install Problem

posted Mar 21, 2015, 9:26 PM by Haris Hashim   [ updated Mar 29, 2015, 1:25 AM ]

* This is a pleminary and live document. Subject to lots of update!

** To continue with my-note-to-self kinda tech blogging. Just because I have done ruby on OpenShift before, but the knowledge is lost to me because I did not blog about it! The different maybe that this time it is a JRuby stuff through DIY cartridge.



OpenShift + JRuby + Magento



The Journey Begin

I am playing around with OpenShift to create a JRuby remote machine so that I can use RubyRep later to sync MySQL database for Point of Sale synchronization purpose. Plus adding a synced online shop later using Magento if things works out. This will be a long blog later. 
However, keep in mind that me and OpenShift have a long history of things that did not works out. Partially because OpenShift is a fast evolving cloud platform. As you guys can see later, changes happened that make things tougher to occasional explorer like me.

The Step Taken Manually

The step is simple and easy to reproduce.
  1. Prerequisite is to have an OpenShift account.
  2. Create an application using Magento (PHP + MySQL 5.5) cartridge..
  3. Use SSH to access the created application shell (this is a long step, do ask if someone need to know).
  4. Manually install JRuby in ~/app-root/runtime folder by downloading the binary tar file using wget shell command and unzip it in that folder. The download link is in JRuby download page.
  5. After doing this, JRuby is installed. As easy as that. Keep in mind that for JRuby to function JDK is the prerequisite. However Open JDK is already installed in DIY cartridge. So no worries there.
  6. However I got stuck here until a good night sleep clear some fatigue. Apparently the bash scripts located in JRuby bin folder actually depent on other application installed in that folder. The scripts do not function since path was not set. So adding "export PATH=$PATH:{path to JRUBY/bin}" finally make things work!
  7. Frustratingly, the thing that I need to work is "jgem install rubyrep" or in other way "jruby -S gem install rubyrep". The error is:
    • "ERROR:  While executing gem ... (SocketError)"     bind: name or service not known" 

The Step with Quickstart Cartridge

  1. With above not working, tried another way that should solve the problem. Previously searching about JRuby and OpenShift give me a result about JRuby "unofficial" quickstart cartridge for OpenShift. Can be found bellow in GitHub
    •  https://github.com/openshift-quickstart/jruby-openshift-quickstart
  2. The step can be found in above page. Generally, first create an application using DIY cartridge.
  3. Optional, use rhc to add MySQL 5.5 cartridge to the application (additional from me, not in the quickstart). 
  4. Merge source code from above github with  DIY cartridge code.
  5. Commit and push it to OpenShift. As a note here, I am using Eclipse plugin for git and OpenShift operation. This in itself deserve a very long blog. Request in comment if anyone interested.
  6. So right here I got stuck with the same error.
    • "ERROR:  While executing gem ... (SocketError)"     bind: name or service not known" OpenShift JRuby Quickstart Error
  7. Troubleshooting, searching, pending solution <==== this is where I am now!

The Conclusion So Far

My instinct is that OpenShift, change or add a strict policy about using out bound ports. Base on my initial (manual) effort that fail and the quickstart cartridge that fail with same error. Logically, that quickstart cartridge must work previously. Otherwise it wont be posted on GitHub as a quickstart cartridge for JRuby on OpenShift. 

Back on my earlier comment that OpenShift is a fast evolving cloud platform. Let me throw in another thought. That this is one of the growing pain of OpenSource. Being opensource, information are shared freely. But, when change happened (and those change easily happened very fast), those information are usually not updated.

So back to the drawing board. More searching on the internet and asking question on OpenShift should help. Crossing my finger that this is solvable.

Comments & Feedback

The gadget spec URL could not be found

Developing and Debugging Shopizer in Eclipse with Maven and Jetty

posted Sep 24, 2014, 9:09 PM by Haris Hashim   [ updated Feb 10, 2015, 11:45 PM ]

!!! NOTE 1: This is still a work in progress with lots of sharp edges that cuts and bleed ;) !!!

Note 2: Prerequisite to follow shopizer documentation Build The Application.


Starting Up

This steps are done using Eclipse Luna.

Good to make sure that latest m2e plugin is installed in eclipse.

Git clone of the project give you sm-core and sm-shop folder.

Install AspectJ Development tool (credit to Arjan reply in StackOverflow here). Use the Menu, Help->Install New Software.

Install AspectJ Development Tools


Then install AspectJ Maven connector. Use the Menu, Windows->Preferences. On the preferences windows expand Maven and select Discovery in the tree list on left hand side. After that click Open Catalog button, find AspectJ and put a check mark on it. Click finish to start installation.

Using same step as installing AspectJ Maven connector, but this time install m2e-apt.

The code base actually have 2 sub project. sm-core mentioned above is actually the library part. While sm-shop is web app part that going to be run by jetty.

SM CORE

Import into eclipse as maven project.There is an error in the sm-core pom.xml file for maven-apt-plugin. Modifying maven-apt-plugin version to 1.0.4 make this error go away.

<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>maven-apt-plugin</artifactId>
<version>1.0.4</version>
        ...
</plugin>

Also add maven-source-plugin to sm-core pom file.

        <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>

This plugin is for debugging. Without it browsing sm-core sources from sm-shop using eclipse will result to source not found.

Only do the following step if bellow error is encountered in sm-core.pom.

You need to run build with JDK or have tools.jar on the classpath.
If this occures during eclipse build make sure you run eclipse under  JDK as well 
(com.mysema.maven:apt-maven-plugin:1.0.6:process:default:generate-sources)

This StackOverflow page discus the issue. Solution that work for me is by eis that suggest setting -vm option in eclipse.ini to a specific jdk which is described in this StackOverflow page or even better this wiki page.

SM SHOP

Modify sm-shop pom to include jetty-maven-plugin. This is the magic that will allow us to run and debug Shopizer using jetty.

<plugin>
<groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>8.1.15.v20140411</version>
        <configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
        </configuration>
</plugin>

The scanIntervalSeconds configuration above is for debugging later. This allow java code to be change and debugged without restarting jetty. Functionality called hot swapping.

Test this using mvn jety:run in a terminal/console which result to following errors:

Error:

  • java.lang.NoClassDefFoundError: org/apache/el/ExpressionFactoryImpl
            Adding the following to pom.xml solve the problem as per this link.
   
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper-el</artifactId>
<version>7.0.27</version>
</dependency>
  • Java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE

DEBUG com.mchange.v2.resourcepool.BasicResourcePool: Preparing to destroy resource: com.mchange.v2.c3p0.impl.NewPooledConnection@26e866ca
DEBUG com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool: Preparing to destroy PooledConnection: com.mchange.v2.c3p0.impl.NewPooledConnecti
on@26e866ca
DEBUG com.mchange.v2.c3p0.impl.NewPooledConnection: com.mchange.v2.c3p0.impl.NewPooledConnection@26e866ca closed by a client.
java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE

Apparently this is just a log message and are harmless/not a problem and can be ignored. Refer to link.

Navigate to localhost:8080 or localhost:8080/admin and the web app should come up, alive and kicking.

Cleaning Up

This looks cool. Adding properties like variable declaration in script. Conveniently put version definition at beginning of pom.xml file.

        <properties>
                ...
                <tomcat-jasper-el.version>7.0.27</tomcat-jasper-el.version>
<jetty-maven-plugin.version>8.1.15.v20140411</jetty-maven-plugin.version>
</properties>

And changing the version to reflect above properties


        <dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper-el</artifactId>
<version>${tomcat-jasper-el.version}</version>
</dependency>

        ...

        <plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-maven-plugin.version}</version>
</plugin>

Run and Debugging

With mvn in system path variable, running the web app in terminal or command prompt is just the matter of executing 

    mvn jetty:run

Running this in eclipse without just a bit of configuration is simplified with the use of m2e and jetty-maven-plugin.

Click on Run Configurations to configure a new run named start.

Run config button

As bellow configuration in the Run Configurations window. Simply add jetty:run as the goal.

Run Configurations

And don't forget to check Debug Output as we need this in debugging step later.

Click Apply and then the Run button to run it.

Or use the Start shortcut automatically added as bellow:

Start shortcut button automatically added

To debug, set a break point 

Set Breakpoint


And use the Start shortcut in Debug as bellow:

Start Debug Shortcut

Navigate to admin page, enter username/password and click Login.

Admin Page


Check the IDE, If everything is OK, program execution will be paused at the set breakpoint. 

Breakpoint Stop



Disqus for Google Sites

The gadget spec URL could not be found






Gimp, Finally a Single Window Mode

posted Jul 4, 2012, 8:55 PM by Haris Hashim   [ updated Jul 5, 2012, 12:14 AM ]

Gimp Startu
Introduction

Today, finally get the chance to use Gimp 2.8 stable release. What a surprise to experience the new and very sought after UI improvement. Of course, this is not exactly a new thing. Has been available since Gimp 2.7 and even before that due to Gimp open source nature.

However, 2.8 is (and supposed to be) a stable release. So in a way, this is major step ahead and send the right signal to its user base. Hopefully this will negate past developer attitude when it come to user request for improvement.

Ramblings

Hell freeze over might be a better title. After all GIMP developers have for so long insist on not having such UI. To the point of many small improvement or work around. Such as dockable utility windows and exiting Gimp after the last edit window is closed. 

Alas, such improvement did not really address the UI clutter and non usability. Hence this new Single Window mode! 

Cluttered Windows

Before we proceed further. Let's enjoy the cluttered window view for one last time.


Gimp Cluttered Window


This is how Gimp looks like to most people who who tend to edit multiple image. The desktop is typically in the background. It is advantageous with ability to drag image files from desktop into Gimp.

The clutter start when one use another program alongside it. A typical scenario is launching web browser while using Gimp. And then pressing Alt-Tab (or use the taskbar) to go back to an edited image.

First of all desktop is no logger in the background. This is now the browser since it was the last opened window. Other editable Gimp window are also hidden by the browser window. So to get back to having Desktop as background with all edit window open will require lots of adjustment. More works when navigating through many open application at the same time.

Distraction Abounds

It is not enough to wrestle with making windows bubble up to the foreground. When ever changing background is most of the time a distraction. Only way to rid that distraction is by maximizing current edit windows. There goes the advantage of viewing multiple image at the same time. To the chagrin of the user, the maximized window does not stay on top. But covered by utility windows that function as short cut to various functions of Gimp. 

The prominent example is Tool window. But typical users will have more than one of such utility window opened. These utility windows will overlaps each other, vying for your attention! Editing large image or zooming in for detail will then become an exercise of  moving stuff out of the way. As well as clicking here and there to get the tool you need in front.

In short, the UI tends to get in your face instead of getting work done!

The Taskbar is the Tab

Not to forget the most annoying feature of Gimp. It economically and efficiently use Windows taskbar as a way to navigate between edit windows. Yes, I am talking about that Window taskbar that have Start Bar, commonly use application ico and list of currently open application. When using Gimp; all those window clutter will also clutter the taskbar! 

To be fair. Gimp was originally developed for Linux on Gnome Desktop Environment. Which have been enjoying Virtual Desktop functionality built in and by default. In such environment, Gimp works well as one can open it in a virtual desktop with its own taskbar.

Not so for Windows user. The more you love it, the more cluttersome it become. Just awesome!

The Solution

So Gimp 2.8 come with optionto enable what we call Single Window mode. To enable this mode. Open up the Windows menu and click Single Window mode check box found at the bottom.

Enable S


The solution is in the form of tabbed window UI. With other utility window neatly docked and conveniently out of the way. Gimp 2.8 also allow multiple column of such docked window. Which further make thing customizable according to user need.

Apparently one can still have floating utility window as long as it is not the Tool window. Which is locked at the right hand side of the screen. Also, there is no way to float or view two image at the same time. Hence the aptly named Single Window mode.

No more Windows taskbar clutter. If more than one image is opened, they are shown at the top as tab with image preview. Moving between editors is much like navigating in tabbed browser such as Firefox or Chrome. Let's see some screen shot.

Single Window View

Simply love it. Expect this one mean open source graphic editing program to get more use in the near future! But read the closing first. Because not all is rosy with this posy.

In Closing

The Gimp has been well known as one clunky foxy. There is still existing or new issue that is noticed while writing this article.

1. It crash few times. Can easily result to lost of works, so safe often. This is an irony since Gimp 2.8 is a stable release!

2. Tabbed UI is not an ideal MDI (Multiple Document Interface) for viewing or editing few pictures at the same time. This is often useful during copy/paste operation or when comparing pictures.

3. Column for docked utility windows is a move in the right direction. Would be nicer if the colum can further split into rows or at least top and bottom area.

4. One not so obvious trick of drag and drop file to open them in Gimp. Is to drag it into Tool window until the mouse cursor showa the plus icon.It will be more obvious to drag a file into the tab area. Doing so result to nothing happen even though a mouse cursor with plus icon is shown.

5. In one occasion, dropping a file into Gimp cause it to automatically maximize the whole application window. Annoy me much since I was planning to drag and drop some files.

6. This next one make me think that Gimp developers are sadistic. The coolest feature of gimp is ability to save to multiple format. Which is a breeze. Just open the save window and save by typing different extension like ".jpg" or ".png". It work great with "Save As" and "Save a Copy". This no longer true. Now one need to use the Export command in File menu. Otherwise this error message will be shown. 

"You can use this dialog to save to the GIMP XCF format..." Why oh why developers! 

Only XCF



Albeit all this clunkiness. For me, there is still hope. Just think of it as year one for an open source release. All those annoying points tend to get fixed sooner or later. Let's hope it is sooner rather than later. 


Flowchart-a-Licious

posted Mar 26, 2012, 2:17 AM by Haris Hashim   [ updated Mar 26, 2012, 4:02 AM ]


Introduction

Last week, a student come to me with question about Arduino. After several communication through FB message and email. I finally pronounce that it is not Arduino problem. And the solution is flow chart!

I was split about this write up. Should it be under the Tech Bloging or Live Blogging category? Well, let's inject some live into tech! That is also why this is my first tech blog that start with ramblings.

Ramblings

There is this one Facebook page that I use to park my company present. As well as catch those people who search for Arduino in Malaysia through Facebook. I begin to think that this is not an efficient way of doing it (FB Group will do better). Yet in that particular day, a student found that page and begin to ask question.

The first thing not to do when asking such question. Is to dump all source code and expect me to reply. The second thing not to do. Is doing the first without making an effort to describe the source code. Zoom into the problem and identify which part of the code that is not working.

When both of this happen. It demonstrate that the code dump is not understood. Hence why it is not working. In that particular day I was right with this line of thought.

Right and Wrong

Arduino is damn easy. With lots of sample program on the internet. So let's put it on the table that many example code can easily be downloaded, studied and used. 

This is not wrong!

However, inability to understand how the example code flow and solve a problem. Will lead to codes being downloaded, not studied and used. 

This is wrong!

In this modern age, universities and colleges realized that programming have a far and wide reaching impact. It can be used to solve problem in multiple domain. Hence student is provided with subjects that taught programming. Some of this classes are in accelerated manner to allow student to have a quick grasp about programming and apply them in multiple discipline.

This is right!

However the accelerated nature means that some matter does not get proper attention. Either just a mentioned in a text book. Or something that hardly get addressed in the class. Mentioned it one time, have an exercise and boom! Move on to the next topic. And I have no idea why this happen to the matter of flowcharting technique.

This is wrong!

Because without emphasizing in such technique. Those beautiful codes is just texts without meaning. Codes, which are very useful in teaching student doing programming. Will become useless if it cannot be studied. But to study it the student need to use flowchart as a tool. A tool that teach the concept of program flow.

Program Flow

So, several email later reveal that the problem is not Arduino specific. But the inability to understand the very concept of programming it self. 

So on Sunday. I invited the student just for a flowcharting session. With understanding that I will not give final solution in form of code.

The first thing that I did is to use game concept to bridge the understanding between image and flow. In the form of a hastily drawn treasure hunting map with the following story line.
  • A group or student have a starting point.
  • They should find a mosque as their first check point. If the mosques is not found, it is OK to go back home.
  • They should run around the mosque 3 times, at every time checking in to the first check point.
  • On the third round they will be given something.
  • If that something is the treasure they can go home. Otherwise have to repeat again running 3 time around the mosque. Perhaps because too slow :D
The student is asked to draw over the map to indicate the flow of how above step is achieved. This is important as it leads to drawing of arrow that show movement between places or check point.

The part that I like most is running around the mosque is indicated by 3 different line around it. I found that when tracing loop in flowchart or source code. It helps to visualize the loop by drawing circle as many as the required iteration! Also symbolizing a virtual concept of iteration using physical drawn line.

The first thing that happened is that the student try to accomplish the task speedily. By just drawing one line from starting point to the last point. This is not a good idea as one line would not show arrow. And by doing it too fast, the lesson of flowchart is lost!

So concept of check point is introduced. Seeing arrows from check point to checkpoint emphasize that there is flow. While stopping at checkpoint slow things down a bit so that I can ask question about what is needed  to be done at that particular point! 

This give birth to the concept of choice. For instant, upon arriving at the first checkpoint, I can ask what should the treasure hunter do there. Should they ask whether they see a mosque or not? Or at each round around the mosque, should they keep track how many round already? After the rounds is done should they check whether treasure is given or not?

Flowcharting

After above exercise is done, come the hard task of representing the treasure hunting activity as flowchart. I.e. drawing shapes that represents input, process and choice. And using this basic building block to construct a loop.

I have to admit that in such 1 to 1 dynamic activity. It is not just the one who being taught that get taught. For instance I suggest an incorrect condition to count the round. Which is if count is equal to 3. To add to this, initially we have no process to reset the count. 

So there we are laughing through our first infinite loop! When count is not reset, the next condition check will never be false. Hence the round around the mosque will happen again and again not seeing the stop condition.

This is when making mistake is not necessarily a wrong thing. I can see that much more learning is actually happening when mistake is made.A point when I can see glimmer of understanding finally creep through in the eye of the student. 

When the flowchart is done. I asked the student to retrace the step to be confident about correctness. Some people might miss this. But this is what we software developer called debugging. Albeit in a much basic form.

Repetition is Good

After the first flowchart is done. I draw another simple map with different task. And we go over the whole process again. We did this for another 2 problem. The last one is done in 2 stage. Where second stage is extending the first.

I found that this kind of repetition is good. I forgot to demonstrate several key concept and it got mentioned later. It is also very good to the student as they will learn more at each repetition. However the important thing is to make them understand instead of memorize. So in the second exercise, the student is allowed to refer back to the first's flowchart. But the third is done in a close book way.

This is important, more so in Malaysia. I remember even in my day. Students tend to memorize more than trying to understand what they are doing.

Analytical Skill

At one point the student ask me a question. I ask back, to find the answer without asking me. And show how to do it by tracing the flowchart that is somewhat modified to cater for doing something wrongly. For instant what if initialization code is inside the loop? If count is set to zero in the loop itself?

With respect to Arduino. There is two main function which is setup() and loop(). The question being why count have to be set to zero in setup instead of the loop.

So we trace the flowchart and observe the effect. This is where the analytical part happen. And I found this to be an important way to understand the flow. In future I would do more of this. In the style of introducing error into the flow chart or mutating the codes. And ask student to trace and observe the effect.

It also make me realize that if I do it in such a way and ask student to answer their own question. It will improve self confident if they got it right. But also make them realize the value of repetition, By making them repeat the process until they got it right! 

In Closing

The whole exercise just make me think about how to handle student request for help. In the beginning of my Arduino day at Homebrew & Technology. I am quite eager to meet student and see what they are doing with Arduino. Soon after, I was flabbergasted by request that does not even demonstrate effort to understand what is being done. More to the tune of "we buy stuff from you, so you have to help us".

Since then I just stop seeing student. It really hurt my eye to see them struggle with doing programming and claim that it is Arduino problem!

At the same time I do have the passion of helping other people. And at least, do have some of the pedagogical facility and tactic to approach this kind of "teaching" requirement. 

The best student I ever have is a student coming to me for knowledge of playing Ping Pong (table tennis). Well I am a student my self at that time. So the solution is to give him a study table made of wood (that just happen to be lying around at that time) that is pushed against a stone wall. And ask him to practice in such a small table. Have to admit that my first intention is to to conquer the "actual" Ping Pong table. With as less disturbance as I can get. But it does work and the guy did become better very fast!

So this will be my strategy moving forward (not asking student to play ping pong against the wall !!!). Those student who come to me asking about Arduino and have plan to dump a lot of codes in front of my eye ball. You guys better be top notch in programming.

Those student who are not, will not be rejected. But be prepared to spend a lot of time doing flow chart. I will not touch on your code or your final project requirement in a flow chart session. 

To be very clear. This requirement is for student only. Professional? Just come and bring a lot of money ;)

pgAdmin Graphically Change postgres Admin Password

posted Mar 25, 2012, 4:39 AM by Haris Hashim   [ updated Mar 25, 2012, 8:14 AM ]






Introduction

How to change postgres account password? In case of forgotten password, hence unable to access the database management GUI. This is my experience when using Windows. It might be the same with other operating system.

The Command Prompt Way

First let me put a note using command prompt technique. The GUI technique is much simpler and presented later in this same writeup.

To do this using command prompt. It is good to know that in windows there will be 2 account. One is postgres windows user account. The other is database admin account. Which is also called postgres.

  • Edit E:\PostgreSQL\9.1\pg_hba.conf and set the localhost method to trust instead of md5.  Do not forget to save.
  • Use the usual Windows way to reset the password of windows user account.
  • Open up a command prompt and use runas to open another command prompt as postgres user.
  • open up Services manager and restart postgresql service. There might be need to update the postgres user account password setting in the service property at this step.
  • Now running psql will not ask any password.
  • Use the following sql to set the user password
ALTER USER Postgres WITH PASSWORD '<newpassword>'
  • Revert the pg_hba.conf localhost method back to md5 .
  • Restart postgresql service in Services manager.

Using pgAdmin to Graphically Reset the Password

This is simpler and I would say faster. Just accidentally found that if pg_hba.conf localhost method is set to trust. There is no need to enter password when connecting to the database using pgAdmin.

Some of the step are similar to when using command prompt technique.

1. Edit E:\PostgreSQL\9.1\pg_hba.conf and set the localhost method to trust instead of md5. Do not forget to save.

pg_hba config file

2. Open up Services manager and restart postgresql service. 

restart postgresql service

3. Run pgAdmin and connect to the database. Note that it will not ask the password since we are in the trust mode.

Start pgAdmin


4. Scroll down to look for postgres database user under Login Roles and open up the properties windows.

Properties for user postgresql

5. Surprisingly there is a tab named Definition that allow for password change. Do the necessary!

Definition tab to change password

6. After this is done, revert back changes to pg_hba.conf file to md5 and restart the postgresql service in Services manager.

7. You should be able to connect to the database. This time using the new password!

In Closing

I learn the hard way about not writing up this stuff earlier. Wasting time looking for good tutorial on how to do this ;)

1-10 of 14