Popular Posts
ADD ... THEN ... UNTIL ... data: begin of SERIES, N1 type I value 10, N2 type I value 20, N3 type I value 30, N4 type I value 40, ... Remove file not in list Append soap header into axis When axis generate classese of web service, it won't include the request of soap header. Here is a way to append soap header manually i...
Stats
Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts
Compile source via JavaCompiler
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

/**
 * Created by nanashi07 on 15/12/13.
 */
public class CompileOnFly {

    public static void main(String args[]) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

        StringWriter writer = new StringWriter();
        PrintWriter out = new PrintWriter(writer);
        out.println("package com.prhythm.output;");
        out.println();
        out.println("public class OutputImpl implements IOutput {");
        out.println();
        out.println("   public void printFor(String message) {");
        out.println("       System.out.printf(\"Print from %s : %s%n\", getClass().getName(), message);");
        out.println("   }");
        out.println();
        out.println("}");
        out.close();
        JavaFileObject file = new TextJavaObject("com.prhythm.output.OutputImpl", writer.toString());

        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
        JavaCompiler.CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

        boolean success = task.call();
        for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
            System.out.printf("Code: %s%n", diagnostic.getCode());
            System.out.printf("Kind: %s%n", diagnostic.getKind());
            System.out.printf("Position: %s%n", diagnostic.getPosition());
            System.out.printf("StartPosition: %s%n", diagnostic.getStartPosition());
            System.out.printf("EndPosition: %s%n", diagnostic.getEndPosition());
            System.out.printf("Source: %s%n", diagnostic.getSource());
            System.out.printf("Message: %s%n", diagnostic.getMessage(null));
        }

        if (success) {
            try {
                URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new File("").toURI().toURL()});
                Class<?> outClass = Class.forName("com.prhythm.output.OutputImpl", true, classLoader);
                Object outInstance = outClass.newInstance();
                outClass.getDeclaredMethod("printFor", new Class[]{String.class}).invoke(outInstance, "Bruce");
            } catch (ClassNotFoundException e) {
                System.err.println("Class not found: " + e);
            } catch (NoSuchMethodException e) {
                System.err.println("No such method: " + e);
            } catch (IllegalAccessException e) {
                System.err.println("Illegal access: " + e);
            } catch (InvocationTargetException e) {
                System.err.println("Invocation target: " + e);
            } catch (InstantiationException e) {
                System.err.println("Initialize instance: " + e);
            }
        }
    }
}

class TextJavaObject extends SimpleJavaFileObject {
    final String code;

    TextJavaObject(String name, String code) {
        super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return code;
    }
}

Output:

Print from com.prhythm.output.OutputImpl : Bruce
Annotation processor on Intellij IDEA
Project structure
+ ---- annotation- processor
| + ---- annotation- lib
|   + ---- build.gradle
|   + ---- src
|     + ---- main
|     | + ---- java
|     |   + ---- com
|     |     + ---- prhythm
|     |       + ---- annotations
|     |         + ---- PrintUsage.java
|     |         + ---- PrintUsageProcessor.java
|     | + ---- resources
|         + ---- META-INF
|           + ---- services
|             + ---- javax.annotation.processing.Processor
| + ---- foo
|   + ---- build.gradle
|   + ---- src
|     + ---- main
|       + ---- java
|         + ---- com
|           + ---- prhythm
|             + ---- foo
|               + ---- Bar.java
| + ---- build.gradle
| + ---- settings.gradle

PrintUsage.java
package com.prhythm.annotations;

/**
 * Print usage
 * Created by nanashi07 on 15/12/2.
 */
public @interface PrintUsage {
}

PrintUsageProcessor.java
package com.prhythm.annotations;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;

/**
 * Processor of {@link PrintUsage}
 * Created by nanashi07 on 15/12/2.
 */
@SupportedAnnotationTypes("com.prhythm.annotations.PrintUsage")
public class PrintUsageProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) {
        Messager messager = processingEnv.getMessager();
        for (TypeElement typeElement : annotations) {
            for (Element element : roundEnv.getElementsAnnotatedWith(typeElement)) {
                String msg = String.format("Use %s on %s#%s", typeElement, element.getEnclosingElement(), element);
                messager.printMessage(Diagnostic.Kind.NOTE, msg);
            }
        }
        return true;
    }
}

javax.annotation.processing.Processor
com.prhythm.annotations.PrintUsageProcessor

Bar.java
package com.prhythm.foo;

import com.prhythm.annotations.PrintUsage;

/**
 * Test class
 * Created by nanashi07 on 15/12/2.
 */
public class Bar {

    @PrintUsage
    public void move(String name) {

    }

    @PrintUsage
    public long time() {
        return System.currentTimeMillis();
    }

}

build.gradle (foo)
group 'com.prhythm'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.6

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile project(':annotation-lib')
}

Enable annotation processor on preference




Build with gradle

gradle clean build

result


References:



Type Memo

Note: ==================================================
Note: TypeElement: com.prhythm.annotations.PrintUsage
Note: TypeElement.getClass(): class com.sun.tools.javac.code.Symbol$ClassSymbol
Note: TypeElement.getSimpleName(): PrintUsage
Note: TypeElement.getEnclosedElements(): 
Note: TypeElement.getEnclosingElement(): com.prhythm.annotations
Note: TypeElement.getInterfaces(): java.lang.annotation.Annotation
Note: TypeElement.getNestingKind(): TOP_LEVEL
Note: TypeElement.getQualifiedName(): com.prhythm.annotations.PrintUsage
Note: TypeElement.getSuperclass(): none
Note: TypeElement.getTypeParameters(): 
Note: TypeElement.getAnnotationMirrors(): 
Note: TypeElement.asType(): com.prhythm.annotations.PrintUsage
Note: TypeElement.getKind(): ANNOTATION_TYPE
Note: TypeElement.getModifiers(): [public, abstract]
Note: ----------------------------------------------------------
Note: Element: move(java.lang.String)
Note: Element.getModifiers(): [public]
Note: Element.getClass(): class com.sun.tools.javac.code.Symbol$MethodSymbol
Note: Element.getKind(): METHOD
Note: Element.getAnnotationMirrors(): @com.prhythm.annotations.PrintUsage
Note: Element.getSimpleName(): move
Note: Element.asType(): (java.lang.String)void
Note: Element.getEnclosedElements(): 
Note: Element.getEnclosingElement(): com.prhythm.foo.Bar
Note: ----------------------------------------------------------
Note: Element: time()
Note: Element.getModifiers(): [public]
Note: Element.getClass(): class com.sun.tools.javac.code.Symbol$MethodSymbol
Note: Element.getKind(): METHOD
Note: Element.getAnnotationMirrors(): @com.prhythm.annotations.PrintUsage
Note: Element.getSimpleName(): time
Note: Element.asType(): ()long
Note: Element.getEnclosedElements(): 
Note: Element.getEnclosingElement(): com.prhythm.foo.Bar
Note: ==================================================
Note: TypeElement: com.prhythm.annotations.Mark
Note: TypeElement.getClass(): class com.sun.tools.javac.code.Symbol$ClassSymbol
Note: TypeElement.getSimpleName(): Mark
Note: TypeElement.getEnclosedElements(): value(),names()
Note: TypeElement.getEnclosingElement(): com.prhythm.annotations
Note: TypeElement.getInterfaces(): java.lang.annotation.Annotation
Note: TypeElement.getNestingKind(): TOP_LEVEL
Note: TypeElement.getQualifiedName(): com.prhythm.annotations.Mark
Note: TypeElement.getSuperclass(): none
Note: TypeElement.getTypeParameters(): 
Note: TypeElement.getAnnotationMirrors(): 
Note: TypeElement.asType(): com.prhythm.annotations.Mark
Note: TypeElement.getKind(): ANNOTATION_TYPE
Note: TypeElement.getModifiers(): [public, abstract]
Note: ----------------------------------------------------------
Note: Element: com.prhythm.foo.Yahoo
Note: Element.getModifiers(): [public, abstract]
Note: Element.getClass(): class com.sun.tools.javac.code.Symbol$ClassSymbol
Note: Element.getKind(): INTERFACE
Note: Element.getAnnotationMirrors(): @com.prhythm.annotations.Mark("2323")
Note: Element.getSimpleName(): Yahoo
Note: Element.asType(): com.prhythm.foo.Yahoo
Note: Element.getEnclosedElements(): home(java.lang.String)
Note: Element.getEnclosingElement(): com.prhythm.foo
Note: ----------------------------------------------------------
Note: Element: home(java.lang.String)
Note: Element.getModifiers(): [public, abstract]
Note: Element.getClass(): class com.sun.tools.javac.code.Symbol$MethodSymbol
Note: Element.getKind(): METHOD
Note: Element.getAnnotationMirrors(): @com.prhythm.annotations.Mark("110"),@com.prhythm.core.generic.http.annotation.Get("https://tw.yahoo.com")
Note: Element.getSimpleName(): home
Note: Element.asType(): (java.lang.String)java.lang.String
Note: Element.getEnclosedElements(): 
Note: Element.getEnclosingElement(): com.prhythm.foo.Yahoo
Display soap message in axis client

client-config.wsdd : should be placed in the root of classpath

<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultClientConfig" xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

    <handler name="log" type="java:org.apache.axis.handlers.LogHandler">
        <!-- If true, output SOAP messages in the console ; otherwise, output in a file. -->
        <parameter name="LogHandler.writeToConsole" value="false" />
        <!-- Specifies the name of the output file when LogHandler.writeToConsole is false -->
        <parameter name="LogHandler.fileName" value="axis.log" />
    </handler>

    <globalConfiguration>
        <parameter name="disablePrettyXML" value="false" />
        <requestFlow>
            <handler type="log" />
        </requestFlow>
        <responseFlow>
            <handler type="log" />
        </responseFlow>
    </globalConfiguration>

    <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender" />
    <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender" />
    <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender" />
</deployment>
JUnit with Spring : orderly test method

When using junit with spring framework for test, to sort execute order of method, will use FixMethodOrder class. It is a little inconvenience because you need to name your test method in correct way.



Execute test method ordered by method name
package com.prhythm.test;

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Created by nanashi07 on 15/6/20.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/application-context.xml")
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OrderedTest {

    @Test
    public void test1() {
        System.out.println("test1 executed");
    }

    @Test
    public void test2() {
        System.out.println("test2 executed");
    }

    @Test
    public void test3() {
        System.out.println("test3 executed");
    }

    @Test
    public void test4() {
        System.out.println("test4 executed");
    }
}
Result:
test1 executed
test2 executed
test3 executed
test4 executed


Now there is an another way to do it.



Create a order annotation for customize order
package org.springframework.test.context.junit4;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by nanashi07 on 15/6/20.
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
    int value();
}
Create a junit runner extends SpringJUnit4ClassRunner
package org.springframework.test.context.junit4;

import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.springframework.test.context.TestContextManager;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
 
public class SpringJUnit4ClassOrderedRunner extends SpringJUnit4ClassRunner {

    /**
     * Constructs a new {@code SpringJUnit4ClassRunner} and initializes a
     * {@link TestContextManager} to provide Spring testing functionality to
     * standard JUnit tests.
     *
     * @param clazz the test class to be run
     * @see #createTestContextManager(Class)
     */
    public SpringJUnit4ClassOrderedRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        Collections.sort(list, new Comparator<FrameworkMethod>() {
            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);

                if (o1 == null || o2 == null)
                    return -1;

                return o1.value() - o2.value();
            }
        });
        return list;
    }
}
Run test as customized order
package com.prhythm.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.Order;
import org.springframework.test.context.junit4.SpringJUnit4ClassOrderedRunner;

/**
 * Created by nanashi07 on 15/6/20.
 */
@RunWith(SpringJUnit4ClassOrderedRunner.class)
@ContextConfiguration("classpath:spring/application-context.xml")
public class OrderedTest {

    @Test
    @Order(value = 4)
    public void test1() {
        System.out.println("test1 executed");
    }

    @Test
    @Order(value = 3)
    public void test2() {
        System.out.println("test2 executed");
    }

    @Test
    @Order(value = 2)
    public void test3() {
        System.out.println("test3 executed");
    }

    @Test
    @Order(value = 1)
    public void test4() {
        System.out.println("test4 executed");
    }
}
Result:
test4 executed
test3 executed
test2 executed
test1 executed
Tired of Hibernate? Try JDBI in your code

JDBI Quick sample



ICategoryDAO.java : create a data access interface (implement is not required)
package com.prhythm.erotic.task.data.dao;

import com.prhythm.erotic.entity.source.Category;
import com.prhythm.erotic.task.data.mapper.CategoryMapper;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import org.skife.jdbi.v2.sqlobject.mixins.Transactional;

import java.util.List;

/**
 * Created by nanashi07 on 15/6/14.
 */
@RegisterMapper(CategoryMapper.class)
public interface ICategoryDAO extends Transactional<ICategoryDAO> {

    @SqlUpdate("insert into Category (Source, Url, Category, SubCategory, Enabled) values (:source, :url, :category, :subCategory, :enabled)")
    int insert(@BindBean Category category);

    @SqlUpdate("update Category set Source = :source, Category = :category, SubCategory = :subCategory, Enabled = :enabled where Url = :url")
    int update(@BindBean Category category);

    @SqlUpdate("update Category set Enabled = :enabled")
    int setEnabled(@Bind("enabled") boolean enabled);

    @SqlQuery("select * from Category where Url = :url")
    Category findCategory(@Bind("url") String url);

    @SqlQuery("select * from Category")
    List<Category> getCategories();

    void close();
}

CategoryMapper.java : create a object mapper for convertion
package com.prhythm.erotic.task.data.mapper;

import com.prhythm.erotic.entity.source.Category;
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Created by nanashi07 on 15/6/14.
 */
public class CategoryMapper extends MetaDataSupport implements ResultSetMapper<Category> {

    @Override
    public Category map(int index, ResultSet r, StatementContext ctx) throws SQLException {
        Category category = new Category();
        if (hasColumn(r, "source")) category.setSource(r.getString("source"));
        if (hasColumn(r, "url")) category.setUrl(r.getString("url"));
        if (hasColumn(r, "category")) category.setCategory(r.getString("category"));
        if (hasColumn(r, "subCategory")) category.setSubCategory(r.getString("subCategory"));
        if (hasColumn(r, "enabled")) category.setEnabled(r.getBoolean("enabled"));
        return category;
    }

}

ICategoryService.java : create a data access service interface
package com.prhythm.erotic.task.data;

import com.prhythm.erotic.entity.source.Category;

import java.util.Collection;
import java.util.List;

/**
 * Created by nanashi07 on 15/6/14.
 */
public interface ICategoryService {

    /**
     * Retrive all categories
     *
     * @return
     */
    List<Category> getCategories();

    /**
     * Update categories
     *
     * @param categories
     * @return
     */
    int updateCategories(Collection<Category> categories);
}

CategoryServiceImpl.java : Implement the data access interface
package com.prhythm.erotic.task.data.impl;

import com.prhythm.erotic.entity.source.Category;
import com.prhythm.erotic.logging.LogHandler;
import com.prhythm.erotic.task.data.ICategoryService;
import com.prhythm.erotic.task.data.dao.ICategoryDAO;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.IDBI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;

/**
 * Created by nanashi07 on 15/6/14.
 */
@Service
public class CategoryServiceImpl implements ICategoryService {

    @Autowired
    IDBI dbi;

    @Override
    public List<Category> getCategories() {
        Handle h = dbi.open();
        ICategoryDAO dao = h.attach(ICategoryDAO.class);

        List<Category> categories = dao.getCategories();

        dao.close();
        h.close();

        return categories;
    }

    @Override
    public int updateCategories(Collection<Category> categories) {
        int count = 0;

        Handle handle = dbi.open();

        try {
            updateCategories(handle, categories);
            handle.commit();
        } catch (Exception e) {
            LogHandler.error(e);
            handle.rollback();
        } finally {
            handle.close();
        }

        return count;
    }

    int updateCategories(Handle handle, Collection<Category> categories) {
        int count = 0;

        ICategoryDAO dao = handle.attach(ICategoryDAO.class);

        // Disable all items
        dao.setEnabled(false);

        for (Category c : categories) {
            Category found = dao.findCategory(c.getUrl());
            if (found == null) {
                count += dao.insert(c);
            } else {
                count += dao.update(c);
            }
        }

        return count;
    }
}

CategoryServiceTester.java : test usage
package com.prhythm.erotic.test.dao;

import com.google.common.base.Stopwatch;
import com.prhythm.erotic.entity.source.Category;
import com.prhythm.erotic.logging.LogHandler;
import com.prhythm.erotic.task.data.ICategoryService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.skife.jdbi.v2.IDBI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Arrays;
import java.util.List;

/**
 * Created by nanashi07 on 15/6/14.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/application-context.xml")
public class CategoryServiceTester {

    @Autowired
    ICategoryService categoryService;

    @Test
    public void testGetCategories() {
        Stopwatch stopwatch = Stopwatch.createStarted();
        List<Category> categories = categoryService.getCategories();
        stopwatch.stop();
        LogHandler.info("%d items loaded in %s", categories.size(), stopwatch);
    }

    @Test
    public void testUpdateCategories() {
        // Get current items
        List<Category> categories = categoryService.getCategories();
        // Append 10 new items
        for (int i = 0; i < 10; i++) {
            Category c = new Category();
            c.setSource("Prhythm");
            c.setUrl("http://app.prhtyhm.com/sample/" + UUID.randomUUID());
            c.setCategory("Blog");
            c.setEnabled(true);
            categories.add(c);
        }

        Stopwatch stopwatch = Stopwatch.createStarted();
        int count = categoryService.updateCategories(categories);
        stopwatch.stop();
        LogHandler.info("%d items updated in %s", count, stopwatch);
    }

}

datasourc.xml
<?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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${com.prhythm.erotic.datasource.driver}"/>
        <property name="url" value="${com.prhythm.erotic.datasource.temp.url}"/>
        <property name="username" value="${com.prhythm.erotic.datasource.user}"/>
        <property name="password" value="${com.prhythm.erotic.datasource.password}"/>
    </bean>

    <tx:annotation-driven transaction-manager="txManager"/>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="dataSource"/>
    </bean>

    <bean id="txDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
        <constructor-arg ref="dataSource"/>
    </bean>

    <bean class="org.skife.jdbi.v2.DBI" depends-on="txManager">
        <constructor-arg ref="txDataSource"/>
        <property name="SQLLog">
            <bean class="com.prhythm.erotic.task.logging.SQLLogAppender"/>
        </property>
    </bean>

</beans>
Dynamic add classpath path
public void appendClasspath(String path) throws NoSuchMethodException, MalformedURLException, InvocationTargetException, IllegalAccessException {
    Path externalResourcesFolder = Paths.get(path);
    ClassLoader sysLoader = ClassLoader.getSystemClassLoader();
    if (sysLoader instanceof URLClassLoader) {
        Class<URLClassLoader> sysLoaderClass = URLClassLoader.class;

        // Use reflection to invoke the private addURL method
        Method method = sysLoaderClass.getDeclaredMethod("addURL", URL.class);
        method.setAccessible(true);
        method.invoke(sysLoader, externalResourcesFolder.toUri().toURL());

        System.out.printf("classpath: %s loaded%n", path);
    }
}
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);
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...
    }
}
Test mail sender
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import bruce.lib.swing.SwingWrench;
import bruce.lib.util.DateTime;
import bruce.lib.util.PostCenter;

public class PostMan extends JFrame {

    JTextField txtIP;
    JTextField txtPort;
    JTextField txtAccount;
    JPasswordField txtPassword;

    JTextField txtSenderMail;
    JTextField txtSednerName;
    JTextField txtReceiverMail;

    JCheckBox cbIsHtml;
    JTextField txtSubject;
    JTextArea txtBody;

    JButton btnSubmit;

    JTextArea txtConsole;

    public PostMan() {
        setLayout(new GridBagLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("發信測試");

        JPanel control = new JPanel(new GridBagLayout());
        control.setMinimumSize(new Dimension(350, 100));

        control.add(new JLabel("主機ip"), new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtIP = new JTextField("ms2.ccic.com.tw", 10), new GridBagConstraints(2, 1, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JLabel("通訊埠"), new GridBagConstraints(3, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtPort = new JTextField("25", 3), new GridBagConstraints(4, 1, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("帳號"), new GridBagConstraints(1, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtAccount = new JTextField("gp_report", 10), new GridBagConstraints(2, 2, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JLabel("密碼"), new GridBagConstraints(3, 2, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtPassword = new JPasswordField("29952666", 10), new GridBagConstraints(4, 2, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("寄件人名稱"), new GridBagConstraints(1, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtSednerName = new JTextField("MES系統訊息", 10), new GridBagConstraints(2, 3, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JLabel("寄件人mail"), new GridBagConstraints(3, 3, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtSenderMail = new JTextField("gp_report@ccic.com.tw", 10), new GridBagConstraints(4, 3, 1, 1, 0.3, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("收件人"), new GridBagConstraints(1, 4, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtReceiverMail = new JTextField("", 10), new GridBagConstraints(2, 4, 3, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("html格式"), new GridBagConstraints(1, 5, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(cbIsHtml = new JCheckBox(), new GridBagConstraints(2, 5, 3, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));

        control.add(new JLabel("主旨"), new GridBagConstraints(1, 6, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        control.add(txtSubject = new JTextField("", 10), new GridBagConstraints(2, 6, 3, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3, 3, 3, 3), 1, 1));
        control.add(new JScrollPane(txtBody = new JTextArea()), new GridBagConstraints(1, 7, 4, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 1, 1));

        add(control, new GridBagConstraints(1, 1, 1, 2, 0, 1, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(3, 3, 3, 3), 1, 1));

        add(new JLabel("LOG"), new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        add(btnSubmit = new JButton("發送"), new GridBagConstraints(3, 1, 1, 1, 0, 0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(3, 3, 3, 3), 1, 1));
        add(new JScrollPane(txtConsole = new JTextArea()), new GridBagConstraints(2, 2, 2, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 1, 1));

        btnSubmit.addActionListener(btnSubmit_Click);

        // redirect console
        System.setOut(new PrintStream(new OutputStream() {

            StringBuffer buffer = new StringBuffer();

            @Override
            public void write(int b) throws IOException {
                switch (b) {
                case '\n':
                    txtConsole.append(buffer.toString() + System.getProperty("line.separator"));
                    buffer.delete(0, buffer.length() - 1);
                    break;
                default:
                    buffer.append((char) b);
                    break;
                }
            }
        }));

        setSize(600, 400);
        SwingWrench.setLocationCenter(this);
    }

    private ActionListener btnSubmit_Click = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {

            try {
                System.out.printf("==========Try sending mail at %s==========%n", DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));

                PostCenter<PostCenter> pc = new PostCenter<PostCenter>();

                pc.init(txtIP.getText().trim(), Integer.parseInt(txtPort.getText().trim()), true, txtAccount.getText().trim(), txtPassword.getText().trim());
                pc.setDebug(true);
                pc.setDebugOut(System.out);
                pc.setEncoding("UTF-8");

                if (txtSednerName.getText().trim().length() == 0)
                    pc.setSender(txtSenderMail.getText().trim());
                else
                    pc.setSender(txtSenderMail.getText().trim(), txtSednerName.getText().trim());

                String[] receivers = txtReceiverMail.getText().replaceAll("\\s", "").replaceAll(",", ";").split(";");

                for (String s : receivers) {
                    pc.addReceiver(s);
                }

                pc.send(txtSubject.getText(), txtBody.getText(), cbIsHtml.isSelected());
            } catch (Exception ex) {
                ex.printStackTrace(System.out);
            }

            System.out.println();
            System.out.println();
            System.out.println();
        }
    };

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new PostMan().setVisible(true);
    }

}
Clipboard Usage
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

public class ClipboardUsage implements ClipboardOwner {

    public void setClipboardContents(String aString) {
        StringSelection stringSelection = new StringSelection(aString);
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(stringSelection, this);
    }

    public String getClipboardContents() {
        String result = "";
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        // odd: the Object param of getContents is not currently used
        Transferable contents = clipboard.getContents(null);
        boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor);
        if (hasTransferableText) {
            try {
                result = (String) contents.getTransferData(DataFlavor.stringFlavor);
            } catch (UnsupportedFlavorException ex) {
                // highly unlikely since we are using a standard DataFlavor
                System.out.println(ex);
                ex.printStackTrace();
            } catch (IOException ex) {
                System.out.println(ex);
                ex.printStackTrace();
            }
        }
        return result;
    }

    @Override
    public void lostOwnership(Clipboard clipboard, Transferable contents) {

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        ClipboardUsage cu = new ClipboardUsage();
        System.out.printf("Clipboard : %s%n", cu.getClipboardContents());
        cu.setClipboardContents("clipboard test.");
        System.out.printf("Clipboard : %s%n", cu.getClipboardContents());
    }

}
JTable : multi line cell
table.getColumnModel().getColumn(i).setCellRenderer(new DefaultTableCellRenderer() {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        String v = (String) value;
        String[] vs = v.split("\n");

        JPanel p = new JPanel(new GridLayout(vs.length, 1)) {
            @Override
            public void setForeground(Color fg) {
                for (int i = 0; i < getComponentCount(); i++) {
                    getComponent(i).setForeground(fg);
                }
                super.setForeground(fg);
            }

            @Override
            public void setBackground(Color bg) {
                for (int i = 0; i < getComponentCount(); i++) {
                    getComponent(i).setBackground(bg);
                }
                super.setBackground(bg);
            }
        };

        // 內容
        for (String s : vs) {
            JLabel l = new JLabel(s, JLabel.LEFT);
            l.setOpaque(true);
            p.add(l);
        }
        // 列高
        table.setRowHeight(row, table.getRowHeight() * vs.length);

        // 顏色設定
        p.setOpaque(true);
        p.setBackground(Color.white);

        // 變更背景及字體 顏色同, 同時變更內部元件的顏色
        if (isSelected) {
            p.setBackground(UIManager.getColor("Table.selectionBackground"));
            p.setForeground(UIManager.getColor("Table.selectionForeground"));
        }

        if (hasFocus) {
            p.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));

            if (table.isCellEditable(row, column)) {
                p.setForeground(UIManager.getColor("Table.focusCellForeground"));
                p.setBackground(UIManager.getColor("Table.focusCellBackground"));
            }
        } else {
            p.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        }

        return p;
    }
});
Programmingly end cell edit mode of jtable
// The following code saves the current value in the cell being edited
// and stops the editing process:
if (table.getCellEditor() != null) {
    table.getCellEditor().stopCellEditing();
}
// The following code discards any changes made by the user and stops
// the editing process:
if (table.getCellEditor() != null) {
    table.getCellEditor().cancelCellEditing();
}
Test polymorphism in reflection method invoke
package y11.m04;

import java.lang.reflect.Method;

public class d28t01 {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // Test polymorphism in reflection
        Object invoker = new Invoker();
        Class clazz = invoker.getClass();

        Dialer p1 = new Phone("12345");
        Phone p2 = new Phone("234567");
        CellPhone p3 = new CellPhone("345678");

        // cause java.lang.NosuchMethodException
        try {
            Method m1 = clazz.getDeclaredMethod("use", p1.getClass());
            m1.invoke(invoker, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Method m2 = clazz.getDeclaredMethod("use", p2.getClass());
            m2.invoke(invoker, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Method m3 = clazz.getDeclaredMethod("use", p3.getClass());
            m3.invoke(invoker, p1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Method[] ms = clazz.getDeclaredMethods();
        for (Method m : ms) {
            if (m.getName().equals("use")) {
                Class[] paramTypes = m.getParameterTypes();
                if (paramTypes.length == 1 && paramTypes[0].isAssignableFrom(p1.getClass())) {
                    m.invoke(invoker, p1);
                }
            }

            if (m.getName().equals("use")) {
                Class[] paramTypes = m.getParameterTypes();
                if (paramTypes.length == 1 && paramTypes[0].isAssignableFrom(p2.getClass())) {
                    m.invoke(invoker, p2);
                }
            }

            if (m.getName().equals("use")) {
                Class[] paramTypes = m.getParameterTypes();
                if (paramTypes.length == 1 && paramTypes[0].isAssignableFrom(p3.getClass())) {
                    m.invoke(invoker, p3);
                }
            }
        }
    }
}

class Invoker {
    public void use(Dialer dialer) {
        if (dialer != null)
            dialer.call();
    }
}

interface Dialer {
    void call();
}

class Phone implements Dialer {
    public String number;

    public Phone(String number) {
        this.number = number;
    }

    public void call() {
        System.out.printf("Call %s%n", number);
    }
}

class CellPhone extends Phone {

    public CellPhone(String number) {
        super(number);
    }

    @Override
    public void call() {
        System.out.printf("Dial %s%n", number);
    }
}
Tick
Start tick
Java Javascript .net
Tick = 0 (GMT+0) 1970/01/01 00:00:00 1970/01/01 00:00:00 1601/01/01 00:00:00
sec/tick 1000 1000 10000000
Convertion
tick=0\to tick Java Javascript .net
Java x 0 621356256000000000
Javascript 0 x 621356256000000000
.net -11644473600000 -11644473600000 x
// Convert c# date to javascript
var ticks = (DateTime.Now.Ticks - 621356256000000000) / 10000;
// Convert javascript date to c#
var ticks = (((new Date()).getTime() * 10000) + 621355968000000000);
Statement.executeBatch() always returns an array of value -2
The elements in the array returned by the method executeBatch may be one of the following:
  1. A number greater than or equal to zero -- indicates that the command was processed successfully and is an update count giving the number of rows in the database that were affected by the command's execution
  2. A value of -2 -- indicates that the command was processed successfully but that the number of rows affected is unknown
    If one of the commands in a batch update fails to execute properly, this method throws a BatchUpdateException, and a JDBC driver may or may not continue to process the remaining commands in the batch. However, the driver's behavior must be consistent with a particular DBMS, either always continuing to process commands or never continuing to process commands. If the driver continues processing after a failure, the array returned by the method BatchUpdateException.getUpdateCounts will contain as many elements as there are commands in the batch, and at least one of the elements will be the following:
  3. A value of -3 -- indicates that the command failed to execute successfully and occurs only if a driver continues to process commands after a command fails
reference : executeBatch
SqlCommand (Sample)
new SqlCommand() //
.setDebugMode(true)
.setConnection(Connector.get())
.setCommandText("SELECT" +
        "    e.entry_id," +
        "    e.entry_name," +
        "    e.entry_english_name," +
        "    e.entry_description," +
        "    e.entry_sop_path," +
        "    e.entry_cordon," +
        "    e.role_name," +
        "    e.entry_enabled," +
        "    e.group_id," +
        "    e.group_name" +
        " FROM mv_wrk e" +
        " WHERE" +
        "    (&entry_id IS NULL OR UPPER(e.entry_id) LIKE UPPER(&entry_id))" +
        "    AND (&entry_name IS NULL OR UPPER(e.entry_name) LIKE UPPER(&entry_name))" +
        "    AND (&entry_english_name IS NULL OR UPPER(e.entry_english_name) LIKE UPPER(&entry_english_name))" +
        "    AND (&entry_enabled IS NULL OR e.entry_enabled = &entry_enabled)" +
        " ORDER BY e.entry_id ASC")
.addParameter("&entry_id", OracleDataType.VARCHAR2)
.addParameter("&entry_name", OracleDataType.VARCHAR2, null)
.addParameter(new SqlParameter("&entry_english_name", OracleDataType.VARCHAR2))
.addParameter(new SqlParameter("&entry_enabled", OracleDataType.NUMBER).setValue(null))
.setAdapter(new QueryAdapter() {
    @Override
    public void executedQuery(SqlArgument arg) throws Exception {
        ResultSet rs;
        if ((rs = ((QueryArgument) arg).resultset) == null)
            return;

        while (rs.next()) {
            System.err.println(DataMap.fill(rs));
        }
    }
})
.query();
batch
new SqlCommand()
.setDebugMode(true)
.setDebugOut(System.err)
.setConnection(ConnectionUtil.get())
.addCommand("/* 1. &name 2. &aid  3. &time */ INSERT INTO access_log VALUES(&aid, &name, &time)", CommandType.Text, CommandMode.Batch)
.addCommand("SELECT * FROM access_log WHERE rownum < &rows ORDER BY time DESC")
.addParameter("&rows", OracleDataType.INT, 5)
.setAdapter(new QueryListener() {
    @Override
    public boolean executingQuery(SqlArgument arg) throws Exception {
        if (arg.first && arg.mode == CommandMode.Batch)
            for (int i = 0; i < 3; i++) {
                arg.addBatchParameters(
                    new SqlParameter("&name", OracleDataType.VARCHAR2, "bruce"),
                    new SqlParameter("&aid", OracleDataType.VARCHAR2, UUID.randomUUID().toString()),
                    new SqlParameter("&time", OracleDataType.DATE, DateTime.now().toTimestamp())
                );
            }

        return true;
    }

    @Override
    public void executedQuery(SqlArgument arg) throws Exception {
        if (arg.first) {
            UpdateArgument ua = (UpdateArgument) arg;
            System.err.println(Arrays.toString(ua.batchResult));
        } else {
            QueryArgument argument = (QueryArgument) arg;
            if (argument.resultset != null)
                while (argument.resultset.next()) {
                    System.err.println(DataMap.fill(argument.resultset));
                }
        }
    }
})
.query();