Refused to get unsafe header “Content-Disposition”

Hit into this error when tying to get the “Content-Disposition” header using XMLHttpRequest.

Finally found the solution is to include CORS access control headers in HTTP response….

Take note that it’s not Access-Control-Allow-Headers but Access-Control-Expose-Headers

Credit to this stackoverflow post.

 

Business Hour Format

I’m creating a form which allow user to key in multiple days of week with multiple operation hours.

I want the format to save as below, but I found it tedious to reformat for displaying using normal javascript. Look into lodash and found it very handy 🙂

Format to display:

Plunker here

Reference: schema.org

 

Disable WebView Application Being Pull Up and Down

I’ve created a hybrid app using Cordova, and notice I’m able to pull the header down and footer up, which lead to weird behaviour when using the app (at least I feel so).

Normal View

normal view

Pull Up

pull up

pull down

pull down

Adding single line of configuration in config.xml solve the issue. (pheeew… spend couple of hours to research this)

Reference: http://cordova.apache.org/docs/en/6.x/config_ref/index.html
 

Test Driven Development

Just finished Test-Driven Java Development (but will take longer time to digest), and  notice there are few tools/framework worth to share.

Test Driven Development Framework

Unit Test Code Coverage Mocking
JUnit JaCoCo (Java Code Coverage)) Mockito
TestNG EasyMock
Hamcrest PowerMock
AssertJ

Behavior Driven Development Framework

Web Testing
RESTful API Testing
Selenide REST Assured
JBehave
Cucumber

Overall this is quite a good book if you practice TDD, as it include bunch of  hands on tutorial. Personally I think practicing TDD is good if we have solid requirement (or at least not changing every few days), else we will waste a lot of time just to maintain unit test for immature requirement 🙂

 

Yet Another Cleaner Way To Construct CSV String in Java

Accidentally found this util class while reading an ebook, and think it worth sharing since myself always found this a tedious code especially prefix and suffix the string.

We used to construct CSV string as below:

With new StringJoiner util in Java 1.8, we can do it in a cleaner way.

The constructor also allow us to prefix and suffix the string.

 

 

Running Spring Scheduler In Cluster Mode

Facing an issue where the email scheduler job keep sending duplicate activation email to user after they registered to the system.
After some troubleshooting time, found the culprit was actually spring schedule job running separately in separate node under cluster environment.

I then decide to “borrow” the idea from Liquibase on how it ensure only one instance running the changeset at one time. I first create a table call schedule_lock with column below:

By having the job_type column, we can store different schedule job status in single table. lock_time and lock_by simply store the lock  time and host name for easy debugging later. So the idea behind is pretty simple, any job will need to check against the lock status and their job type before running the job.

For eg: Node A run the job, it own the lock by updating is_lock to TRUE, lock_time and lock_by to current time and host name. Now Node B kicks in with the same job, it then check against the column, found is_lock = TRUE, it know some node already performing the job, so it can have some rest time by discard it’s own job.
After Node A complete it’s job, it will then release the lock by updating is_lock to FALSE, lock_time and lock_by to null.

And here is the code snippet for getting and releasing the lock.

OK, seems everything is now in place and my spring scheduler is “cluster safe”, Yay !

BUT … when the job run again with this new implementation, some weird behavior again happen.
Node A and Node B got the lock one after another, Node A release the lock successfully, but Node B throw an exception when releasing the lock. Logs below explain the situation:

Lets zoom into the code and see what is happening.

In this situation, the only possibility I can think of is Node B run the job first and got the lock by updating the record into database, but before Node B commit the changes into database, Node A kicks in safely with lock status still FALSE, so it then overwrite the lock status updated by Node B just almost immediately.

After some thought, I come out with an idea to make them run in different time by setting random Thread sleep time for each of the job and guess what, problem solved 🙂

p/s: This might not be the best way, as the scheduler job will not run in exact 2 minutes we set, in this case will be 2 minutes + Thread sleep time from 1 – 60 sec. Leave me a comment if you have better idea.

 

Create Custom Facebook Fan Page Web Address Without 25 Fans

Facebook will allow us to change our fan page username only once after we create, and we will need at least 25 likes to reset the username subsequently.

So what if you have already used up the first chance, and you don’t have 25 fans yet to change the new username?

Here is the tricks which you can by pass it:

1. Create new facebook account, then create a new fan page from the new account.

2. Goto https://www.facebook.com/username/ to create your new fan page username.
fbfans1
3. Goto Page Settings –> Page Roles then specify an email address (your real facebook login email) to be the page admin, then click Save to apply.
fbfans2

4. And you will see this.
fbfans3

5. You will receive an email as below after few second, just confirm and proceed to login if needed.
fbfans4

6. All set, you can now start managing the new fan page with new username. Follow step here to delete your temporary facebook account if you no longer using it, since this temporary account is also an admin for the fan page, so people who login using this account will be able to delete the fan page 🙂

 

 

Filter Exception Does Not Translate By ExceptionTranslationFilter

If you are having custom servlet filter added into Spring security filter chain, and you are expecting custom filter exception throws should translate by ExceptionTranslationFilter but it doesn’t. Then you probably need to register your custom filter after ExceptionTranslationFilter as below.