Popular Posts
Enable SSL connection for Jsoup import org.jsoup.Connection; import org.jsoup.Jsoup; import javax.net.ssl.*; import java.io.IOException; import java.security.KeyManagement... JDateField package bruce.lib.swing; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.A... Get files name in batch Windows Batch : get filename using [%%~ni] Linux Shell Script : get filename using [awk, sed] windows sample : rename all *.htm file to ...
Stats
ASP.NET MVC 5 Attribute Routing
Enable attribute route
Global.asax
public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // Enable attribute route
        RouteTable.Routes.MapMvcAttributeRoutes();

        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
}
or
RouteConfig.cs
public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            
        // Enable attribute route
        routes.MapMvcAttributeRoutes();

        AreaRegistration.RegisterAllAreas();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}
Direct route
public class BookController : Controller {

    // Map to 'http://prhythm.com.tw/Pet/10'
    [Route("Pet/{id}")]
    public ActionResult Pet(int? id) {
        return View();
    }

}
Optional paramter
public class BookController : Controller {

    // Optional parameter id
    // Map to 'http://prhythm.com.tw/Pet'
    //     or 'http://prhythm.com.tw/Pet/5'
    [Route("Pet/{id?}")]
    public ActionResult Pet(int? id) {
        return View();
    }

}
Default parameter value
public class BookController : Controller {
    
    // Default value of id
    // Map to 'http://prhythm.com.tw/Pet'
    //     or 'http://prhythm.com.tw/Pet/10'
    [Route("Pet/{id=10}")]
    public ActionResult Pet(int? id) {
        return View();
    }

}
Paramter constrains
public class BookController : Controller {
    
    // Paramters constrains
    [Route("Pet/{id:int}")]
    public ActionResult Pet(int? id) {
        return View();
    }

}
ConstraintDescriptionExample
alpha Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z) {x:alpha}
bool Matches a Boolean value. {x:bool}
datetime Matches a DateTime value. {x:datetime}
decimal Matches a decimal value. {x:decimal}
double Matches a 64-bit floating-point value. {x:double}
float Matches a 32-bit floating-point value. {x:float}
guid Matches a GUID value. {x:guid}
int Matches a 32-bit integer value. {x:int}
length Matches a string with the specified length or within a specified range of lengths. {x:length(6)}
{x:length(1,20)}
long Matches a 64-bit integer value. {x:long}
max Matches an integer with a maximum value. {x:max(10)}
maxlength Matches a string with a maximum length. {x:maxlength(10)}
min Matches an integer with a minimum value. {x:min(10)}
minlength Matches a string with a minimum length. {x:minlength(10)}
range Matches an integer within a range of values. {x:range(10,50)}
regex Matches a regular expression. {x:regex(^\d{3}-\d{3}-\d{4}$)}
Route prefix
[RoutePrefix("Booking")]
public class BookController : Controller {

    // Map to 'http://prhythm.com.tw/Booking'
    //     or 'http://prhythm.com.tw/Booking/Pet'
    [Route]    
    [Route("Pet")]
    public ActionResult Pet() {
        return View();
    }

    // Map to 'http://prhythm.com.tw/Booking/Edit'
    [Route("Edit")
    public ActionResult Edit() {
        return View();
    }
}
Override route prefix
[RoutePrefix("Booking")]
public class BookController : Controller {

    // Override route prefix
    // Map to 'http://prhythm.com.tw/Pet'
    [Route("~/Pet")]
    public ActionResult Pet() {
        return View();
    }
}
Default route
[RoutePrefix("Booking")]
[Route("action=pet")]
public class BookController : Controller {

    // Map to 'http://prhythm.com.tw/Booking'
    //     or 'http://prhythm.com.tw/Booking/Pet'
    public ActionResult Pet() {
        return View();
    }

    // Map to 'http://prhythm.com.tw/Booking/Edit'
    public ActionResult Edit() {
        return View();
    }
}
Route area
[RouteArea("Backend")]
[RoutePrefix("News")]
public class NewsController : Controller {

    // Map to 'http://prhythm.com.tw/backend/news'
    public ActionResult Index() {
        return View();
    }

}
[RouteArea("Backend", AreaPrefix = "Admin")]
[RoutePrefix("News")]
public class NewsController : Controller {

    // Map to 'http://prhythm.com.tw/admin/news'
    public ActionResult Index() {
        return View();
    }

}

Reference http://sampathloku.blogspot.tw/2013/11/attribute-routing-with-aspnet-mvc-5.html

Reference http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx

Asynchronous and deferred JavaScript execution explained
  • Normal execution <script>
    This is the default behavior of the <script> element. Parsing of the HTML code pauses while the script is executing. For slow servers and heavy scripts this means that displaying the webpage will be delayed.
  • Deferred execution <script defer>
    Simply put: delaying script execution until the HTML parser has finished. A positive effect of this attribute is that the DOM will be available for your script. However, since not every browser supports defer yet, don’t rely on it!
  • Asynchronous execution <script async>
    Don’t care when the script will be available? Asynchronous is the best of both worlds: HTML parsing may continue and the script will be executed as soon as it’s ready. I’d recommend this for scripts such as Google Analytics.

Reference : http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/

Reference : http://www.html5rocks.com/en/tutorials/speed/script-loading/

Integration config for spring & hibernate
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.prhythm.spring.web.controller"/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:mem:test"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="com.prhythm.spring.web.model"/>
        <!--<property name="annotatedClasses">-->
            <!--<list>-->
                <!--<value>com.prhythm.spring.web.model.Employee</value>-->
            <!--</list>-->
        <!--</property>-->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.current_session_context_class">thread</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

</beans>
Wrong text encoding while Jsoup parse document

While page encoding is different with content type encoding declaration. Jsoup will get wrong text decode content. To avoid this problem, Assign a correct text encoding will be required.

Connection connection = Jsoup.connect(requestUrl)
        .data("type", "1")
        .data("searchKeyUID", searchKeyUID)
        .timeout(timeout)
        .method(Connection.Method.GET);

Connection.Response response = connection.execute();
Document document = Jsoup.parse(new ByteArrayInputStream(response.bodyAsBytes()), "UTF-8", requestUrl);
Group data on SQLite

Schema

CREATE TABLE invoice
(
    Id INTEGER PRIMARY KEY,
    code TEXT,
    dropped INTEGER,
    due_date INTEGER,
    paid INTEGER,
    due_date2 TEXT
);

Initial data

INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (1, 'IMSS', 0, 1407384129647, 0, '2014-08-07 04:02:09');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (2, 'Deep Discovery family', 0, 1407346684736, 0, '2014-08-06 17:38:04');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (3, 'TMMS​', 1, 1407375568242, 0, '2014-08-07 01:39:28');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (4, 'TMS family​', 0, 1407374437084, 1, '2014-08-07 01:20:37');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (5, 'SafeSync', 0, 1407358168347, 1, '2014-08-06 20:49:28');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (6, 'TMVMS​', 0, 1407350693881, 0, '2014-08-06 18:44:53');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (7, 'TMS family​', 0, 1407372590354, 0, '2014-08-07 00:49:50');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (8, 'IMSVA', 0, 1407344495046, 0, '2014-08-06 17:01:35');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (9, 'Other', 0, 1407351210774, 0, '2014-08-06 18:53:30');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (10, 'Deep Discovery family', 0, 1407372667906, 0, '2014-08-07 00:51:07');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (11, 'IMSVA', 1, 1407365934950, 1, '2014-08-06 22:58:54');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (12, 'PSP', 1, 1407382557767, 1, '2014-08-07 03:35:57');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (13, 'SecureCloud​', 0, 1407371609679, 0, '2014-08-07 00:33:29');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (14, 'NVWE​', 0, 1407383088966, 0, '2014-08-07 03:44:48');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (15, 'ESE', 1, 1407360299869, 1, '2014-08-06 21:24:59');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (16, 'IMSVA', 0, 1407377397832, 0, '2014-08-07 02:09:57');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (17, 'IWSVA​', 0, 1407366067348, 1, '2014-08-06 23:01:07');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (18, 'TMS family​', 1, 1407351067728, 0, '2014-08-06 18:51:07');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (19, 'OSCE​', 0, 1407345046895, 0, '2014-08-06 17:10:46');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (20, 'TIM​', 0, 1407363640638, 1, '2014-08-06 22:20:40');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (21, 'CSS​', 1, 1407330238874, 0, '2014-08-06 13:03:58');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (22, 'TMPS​', 1, 1407321708684, 1, '2014-08-06 10:41:48');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (23, 'TMS family​', 1, 1407319881608, 0, '2014-08-06 10:11:21');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (24, 'SafeSync', 1, 1407306547713, 0, '2014-08-06 06:29:07');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (25, 'ESDP', 0, 1407298566126, 0, '2014-08-06 04:16:06');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (26, 'CSS​', 0, 1407282477671, 0, '2014-08-05 23:47:57');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (27, 'TMMS​', 1, 1407240200509, 1, '2014-08-05 12:03:20');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (28, 'Other', 0, 1407218499996, 0, '2014-08-05 06:01:39');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (29, 'ESE', 0, 1407210588362, 0, '2014-08-05 03:49:48');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (30, 'CSS​', 0, 1407207304034, 0, '2014-08-05 02:55:04');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (31, 'TMVMS​', 1, 1407188482248, 0, '2014-08-04 21:41:22');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (32, 'SecureCloud​', 0, 1407155296508, 0, '2014-08-04 12:28:16');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (33, 'TMS family​', 1, 1407136374493, 0, '2014-08-04 07:12:54');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (34, 'ESE', 1, 1407121543307, 1, '2014-08-04 03:05:43');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (35, 'ScanMail', 0, 1407118018107, 0, '2014-08-04 02:06:58');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (36, 'ScanMail', 0, 1407088856291, 0, '2014-08-03 18:00:56');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (37, 'IMSS', 0, 1407059314747, 1, '2014-08-03 09:48:34');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (38, 'OSCE​', 1, 1407027453954, 0, '2014-08-03 00:57:33');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (39, 'Deep Discovery family', 0, 1406995304204, 0, '2014-08-02 16:01:44');
INSERT INTO invoice (Id, code, dropped, due_date, paid, due_date2) VALUES (40, 'Worry-Free', 0, 1406968142441, 0, '2014-08-02 08:29:02');

Group select

select 
  Id, 
  code, 
  (dropped|paid) status, 
  (due_date < 1407200000000) expired, 
  due_date2 
from invoice 
order by 
  paid|dropped, 
  (due_date > 1407200000000), 
  due_date desc

result

android.intent.action.SCREEN_ON & android.intent.action.SCREEN_OFF

First, I've tried create a receiver to receive screen on/off and register receiver on AndroidManifest.xml like below, but unfortunately it does not work.

ScreenReceiver.java
package com.prhythm.training.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * Created by Bruce on 7/15/2014.
 */
public class ScreenReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("Receiver", String.format("Broadcast action: %s", intent.getAction()));
    }
}
AndroidManifest.xml
<receiver android:name=".service.ScreenReceiver">
    <intent-filter>
        <action android:name="android.intent.action.SCREEN_ON"/>
        <action android:name="android.intent.action.SCREEN_OFF"/>
    </intent-filter>
</receiver>

I's nessary to register screen action receiver by code, so I've change the as

ScreenReceiver.java
package com.prhythm.training.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
 * Created by Bruce on 7/15/2014.
 */
public class ScreenReceiver extends BroadcastReceiver {

    public static ScreenReceiver CURRENT;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("Receiver", String.format("Broadcast action: %s", intent.getAction()));
    }
}
ScreenService.java
package com.prhythm.training.service;

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

/**
 * Created by Bruce on 7/15/2014.
 */
public class ScreenService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        // Register screen on/off receiver
        if (ScreenReceiver.CURRENT == null) ScreenReceiver.CURRENT = new ScreenReceiver();
        getApplicationContext().registerReceiver(ScreenReceiver.CURRENT, new IntentFilter(Intent.ACTION_SCREEN_ON));
        getApplicationContext().registerReceiver(ScreenReceiver.CURRENT, new IntentFilter(Intent.ACTION_SCREEN_OFF));
    }
}

Then, start this service is required

startService(new Intent(this, ScreenService.class));
Enable SSL connection for Jsoup
import org.jsoup.Connection;
import org.jsoup.Jsoup;

import javax.net.ssl.*;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class TaipeiWater {
    
    final static String requestUrl = "https://somewhere.com/target.jsp";

    public static void enableSSLSocket() throws KeyManagementException, NoSuchAlgorithmException {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new X509TrustManager[]{new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }}, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    }

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, KeyManagementException {
        String bigno = "S";
        String midno = "11";
        String useno = "111111";
        String chkno = "1";

        enableSSLSocket();

        Connection.Response response = Jsoup.connect(requestUrl)
                .data("bigno", bigno)
                .data("midno", midno)
                .data("useno", useno)
                .data("chkno", chkno)
                .userAgent("Mozilla/5.0 (Windows NT 6.2; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0")
                .method(Connection.Method.POST)
                .execute();

        switch (response.statusCode()) {
            case 200:
                doProcess(response.parse());
                break;
            default:
                
                break;
        }
    }

    public static void doProcess(Document document){
        // do something...
    }
}
Register preference change event with PreferenceFragment
public class DevicePreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preference);
    }

    @Override
    public void onResume() {
        super.onResume();
        getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);

    }

    @Override
    public void onPause() {
        getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
        super.onPause();
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        Log.d(MainActivity.TAG, String.format("Preference '%s' has been changed.", key));
        if ("pref_track_interval".equals(key)) {
            // do something
        }
    }
}
Set remote respository for Intellij IDEA git integration
  1. Create a new project
  2. VCS -> Import into Version Control -> Create Git Repository... , then select the project path
  3. Open project path, find the config file at hidden subfolder .git
    Edit config file, add following contents at end:
    [remote "origin"]
     url = http://www.yourgitserver.com/repository.git
     fetch = +refs/heads/*:refs/remotes/origin/*
  4. File -> Synchronize
  5. That it! Try commit and push your project
Override Response Content-Type with OutputCache

Response content-type will be set as text/html on OutputCache is assigned, even if there is an assignment inside action.

HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [OutputCache(Duration = 60)]
        public ActionResult NavigationScript()
        {
            Response.ContentType = "application/javascript";
            return View();
        }
    }
}
Result

Custom a attribute and change content type after output cache processed.

ResponseHeaderAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Filter
{
    public class ResponseHeaderAttribute : ActionFilterAttribute
    {
        public string ContentType { get; set; }
        public System.Text.Encoding ContentEncoding { get; set; }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (!string.IsNullOrWhiteSpace(ContentType)) filterContext.HttpContext.Response.ContentType = ContentType;
            if (ContentEncoding != null) filterContext.HttpContext.Response.ContentEncoding = ContentEncoding;
        }
    }
}
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebApplication1.Filter;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [OutputCache(Duration = 60, Order = 1)]
        [ResponseHeader(ContentType = "application/javascript", Order = 2)]
        public ActionResult NavigationScript()
        {
            return View();
        }
    }
}
Result