目前分類:java (28)

瀏覽方式: 標題列表 簡短摘要

Lambdas in Java Preview - Part 1: The Basics

Lambdas in Java Preview - Part 2: Functional Java

Lambdas in Java Preview - Part 3: Collections API

Lambdas in Java Preview - Part 4: Proposal Update

Lambdas in Java Preview - Part 5: Apache Wicket

Forth 發表在 痞客邦 留言(1) 人氣()

經歷ASP、PHP、JSP、Tapestry、Wicket、Rails,目前正在使用的是Play framework。開發時只需用內建的server,修改java程式或HTML網頁之後,只要refresh就能看到結果,Play會幫我們編譯java檔。部署時可以用內建的server,也能打包成war檔放進application server,若要部署至Google App Engine也有GAE module可用。Play也把Hibernate包裝好了,使用時不再需要繁瑣的設定。其它如MongoDB、Scala、Spring、GWT等也已經有支援模組。就像Rails,Play也有內建routes功能可以讓你輕鬆開發RESTFul application,或是讓URL看起來漂亮些。

A web app in 10 minutes using Play! from zenexity on Vimeo.


Forth 發表在 痞客邦 留言(0) 人氣()

  • maxConnectionsPerPartition最小值是2,給了小於2的值會被設成50
  • minConnectionsPerPartition最小值是2,給了小於2的值會被設成10
  • minConnectionsPerPartition大於maxConnectionsPerPartition時,會被設成maxConnectionsPerPartition
  • acquireIncrement小於或等於0時,會被設成1
  • partitionCount小於1時,會被設成3
  • releaseHelperThreads小於0時,會被設成3
  • statementsCacheSize小於0時,會被設成0
  • acquireRetryDelay小於或等於0 時,會被設成1000

Forth 發表在 痞客邦 留言(0) 人氣()

有時候要把Maven調教成想要的樣子真的很麻煩,自己刻Ant build file比較快,但是這樣就要自己管理dependencies,引用很多library的時候會很痛苦,還好有Ant Tasks for Maven可以幫忙減輕痛苦。下載maven-ant-tasks-*.jar後扔進$APACHE_HOME/lib目錄就可以用了。

使用時可以像用Maven時一樣,把dependencies資訊存入pom.xml,再從build.xml引用。

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>net.zbwei</groupId>
  <artifactId>bento</artifactId>
  <packaging>war</packaging>
  <name>bento</name>
  <version>0.1</version>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring</artifactId>
      <version>2.5.5</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.3.0.ga</version>
    </dependency>
  </dependencies>
</project>

 

build.xml:

Forth 發表在 痞客邦 留言(0) 人氣()

@Entity
@Table(name="memberships")
@IdClass(MembershipPK.class)
public class Membership {
        private Integer groupId;

        private Integer userId;

        @Id
        @Column(name="group_id")
        public Integer getGroupId() {
                return groupId;
        }

        public void setGroupId(Integer groupId) {
                this.groupId = groupId;
        }

        @Id
        @Column(name="user_id")
        public Integer getUserId() {
                return userId;
        }

        public void setUserId(Integer userId) {
                this.userId = userId;
        }
}
@Embeddable
public class MembershipPK {
        private Integer groupId;

        private Integer userId;

        public Integer getGroupId() {
                return groupId;
        }

        public void setGroupId(Integer groupId) {
                this.groupId = groupId;
        }
        
        public Integer getUserId() {
                return userId;
        }
        
        public void setUserId(Integer userId) {
                this.userId = userId;
        }
}

Forth 發表在 痞客邦 留言(0) 人氣()

在Wicket程式用Spring,要在web.xml加入設定:

<context -param>
  <param -name>contextConfigLocation</param>
  <param -value>/WEB-INF/spring*.xml</param>
</context>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

在WebApplication中要建立SpringComponentInjector:

public class BasicApplication extends WebApplication {
  @Override
  protected void init() {
    super.init();
    addComponentInstantiationListener(new SpringComponentInjector(this));
  }
}

如果還想把bean注入WebSession,要用InjectorHolder:

public class BasicSession extends WebSession {
  public BasicSession(Request request) {
    super(request);
    InjectorHolder.getInjector().inject(this);
  }
}

設定好之後,只要在需要注入bean的地方用@SpringBean即可,範例如下:

public class SignUpPage extends BasePage {
  @SpringBean
  private UserService userService;

  public SignUpPage() {
    add(new SignUpForm("signUpForm"));
  }

  class SignUpForm extends Form {
    private String name;

    private String email;

    private String password;

    @SuppressWarnings("unused")
    private String confirmPassword;

    public SignUpForm(String id) {
      super(id);
      PasswordTextField passwordField, confirmPasswordField;
      add(new TextField("name",  new PropertyModel(this, "name")).setRequired(true).add(new StringValidator.LengthBetweenValidator(2, 32)));
      add(new TextField("email", new PropertyModel(this, "email")).setRequired(true).add(EmailAddressValidator.getInstance()));
      add(passwordField        = new PasswordTextField("password",        new PropertyModel(this, "password")));
      add(confirmPasswordField = new PasswordTextField("confirmPassword", new PropertyModel(this, "confirmPassword")));
      add(new EqualPasswordInputValidator(passwordField, confirmPasswordField));
    }

    @Override
    protected void onSubmit() {
      User user = new User(name, email, password, User.ROLE_USER);
      try {
        userService.createUser(user);
        setResponsePage(HomePage.class);
      } catch (DuplicatedUserNameException e) {
        error(getLocalizer().getString(getId() + ".nameTaken", getWebPage(), "User's name is taken: " + name));
      } catch (DuplicatedUserEmailException e) {
        error(getLocalizer().getString(getId() + ".emailTaken", getWebPage(), "User's email is taken: " + email));
      }
    }
  }
}

Forth 發表在 痞客邦 留言(0) 人氣()

應用程式內嵌Jetty運行webapp時,希望程式和webapp共用同一個spring context,在web.xml設定context loader listener時,要改用自定的MyContextLoaderListener。

JettyServer.java:

import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class JettyServer implements ApplicationContextAware {
  private ApplicationContext applicationContext;

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
     this.applicationContext = applicationContext;
  }

  public void start() throws Exception {
     int port = Integer.parseInt(System.getProperty("jetty.port", "8080"));

    SelectChannelConnector connector = new SelectChannelConnector();
     connector.setPort(port);

    Server server = new Server();
     server.addConnector(connector);

    WebAppContext context = new WebAppContext();
     context.setClassLoader(applicationContext.getClassLoader());
     context.setAttribute("applicationContext", applicationContext);
     context.setServer(server);
     context.setContextPath("/");
     context.setWar("src/main/webapp");

    server.addHandler(context);
     server.start();
  }
}

MyContextLoader.java:

import javax.servlet.ServletContext;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.ContextLoader;

public class MyContextLoader extends ContextLoader {
  @Override
  protected ApplicationContext loadParentContext(ServletContext servletContext) throws BeansException {
     return (ApplicationContext)servletContext.getAttribute("applicationContext");
  }
}

MyContextLoaderListener.java:

import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.ContextLoaderListener;

public class MyContextLoaderListener extends ContextLoaderListener {
  @Override
  protected ContextLoader createContextLoader() {
     return new MyContextLoader();
  }
}

Forth 發表在 痞客邦 留言(0) 人氣()

Maven repository沒有TerracottaTerracotta Maven Plugin,所以要在pom.xml加入:

  <repositories>
    <repository>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>terracotta-repository</id>
      <url>
        http://www.terracotta.org/download/reflector/maven2
      </url>
    </repository>
  </repositories>

  <pluginrepositories>
    <pluginrepository>
      <id>terracotta-snapshots</id>
      <url>
        http://www.terracotta.org/download/reflector/maven2
      </url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </pluginrepository>
  </pluginrepositories>

  <build>
    <plugins>
      <plugin>
        <groupid>org.terracotta.maven.plugins</groupid>
        <artifactid>tc-maven-plugin</artifactid>
        <version>1.0.3</version>

        <configuration>
          
          
          
          

          
          
          
          
          
          
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupid>org.terracotta</groupid>
      <artifactid>terracotta</artifactid>
      <version>2.5.1</version>
    </dependency>
  </dependencies>

不過,Terracotta DSO Eclipse Plug-inTerracotta Maven Plugin好用多了。


Forth 發表在 痞客邦 留言(0) 人氣()

RubyHelp.java:

public class RubyHelper {
  static {
    System.setProperty("jruby.home", new File("").getAbsolutePath());
  }

  private RubyHelper() {
  }

  public static Object create(String className, Class interfaceClazz, String scriptFileName) {
    InputStream scriptInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFileName);
    if (null == scriptInputStream) {
      throw new RuntimeException("Could not find " + scriptFileName);
    }
    StringBuilder sb = new StringBuilder();
    byte[] buf = new byte[8192];
    try {
      for (int n; (n = scriptInputStream.read(buf)) != -1;) {
        sb.append(new String(buf, 0, n, "UTF-8"));
      }
      scriptInputStream.close();
    } catch (IOException e) {
      throw new RuntimeException("Error loading " + scriptFileName + ": " + e.getMessage());
    }
    Ruby runtime = JavaEmbedUtils.initialize(new ArrayList());
    runtime.eval(runtime.parse(sb.toString(), scriptFileName, runtime.getCurrentContext().getCurrentScope(), 0, false));
    return JavaEmbedUtils.rubyToJava(runtime, runtime.evalScriptlet(className + ".new"), interfaceClazz);
  }
}

HelloService.java:

public interface HelloService {
  void hello();
}

hello.rb:

class Hello
  def hello
    puts 'hello there'
  end
end

Test.java:

public class Test {
  public static void main(String[] args) throws Exception {
    HelloService s = (HelloService)RubyHelper.create("Hello", HelloService.class, "hello.rb");
    s.hello();
  }
}

Forth 發表在 痞客邦 留言(0) 人氣()

  • Apache MINA
  • dom4j
  • ehcache
  • FreeMarker
  • Hibernate
  • Hibernate Annotations
  • ini4j
  • JavaMail
  • Java Service Wrapper
  • Jakarta Commons Logging
  • JCIFS
  • Jetty
  • JGoodies Binding
  • JGoodies Forms
  • JGoodies Looks
  • JGoodies Validation
  • Jpcap
  • jTDS
  • log4j
  • Proxool
  • Quartz
  • Spring Framework
  • Wicket
  • XStream
  • YourKit Java Profiler

Forth 發表在 痞客邦 留言(0) 人氣()

下列是DatabaseOperation提供的功能,如果有用IDENTITY欄位,要改用InsertIdentityOperation提供的INSERT、CLEAN_INSERT、REFRESH。

UPDATE 用dataset更新資料,如果資料庫中沒有資料,會被視為錯誤。
INSERT 用dataset建立資料,如果資料庫中已有資料,會被視為錯誤。
DELETE 用資料庫系統的DELETE命令刪除table中的資料,只有在dataset內的資料會被刪除。
DELETE_ALL 用資料庫系統的DELETE命令刪除table中的所有資料,只有dataset列出的table會被影響。
TRUNCATE 用資料庫系統的TRUNCATE命令清除table中的所有資料,只有dataset列出的table會被影響。
REFRESH 用dataset更新和建立資料。已存在的資料會被標新,不存在的資料會被建立。
CLEAN_INSERT 先執行DELETE_ALL,再執行INSERT。

Forth 發表在 痞客邦 留言(0) 人氣()

Wicket開發指南,作者是王磊,這本三百多頁的開發指南,應該是目前對Wicket解說最詳細的中文手冊。我用過的Java web framework只有兩個,Tapestry是第一個,第二個就是Wicket。Tapestry已經被我停用了,位子則由Wicket和Ruby on Rails一同接下。第一次知道Wicket這東西,是在Tapestry作者的blog中瞧見的。在IDE如Eclipse的 協助下,熟悉Java的程序員使用Wicket的開發速度可以非常快,雖然在persistence layer要用JDBC或Hibernate,不如Ruby on Rails的ActiveRecord省事,但在presentation layer的用法則是我所喜愛的,這也是早期採用Tapestry的原因,Rails中調用簡便的AJAX,在Wicket也有良好支援。至於 Struts和Spring MVC,雖然沒事偶爾會看看,但是,看看就好,完全不想用(真是任性啊!)。目前要我開發web app的話,不是Wicket,就是Ruby on Rails了。


Forth 發表在 痞客邦 留言(0) 人氣()

Pro Wicket給我的感想是,快速的用範例簡單的介紹一些元件的用法,然後,沒了,給人少了些什麼的感覺。

Forth 發表在 痞客邦 留言(0) 人氣()

  1. FindBugs
  2. Hibernate Tools
  3. PMD
  4. JInto
  5. DLTK
  6. Subclipse
  7. TestNG

Forth 發表在 痞客邦 留言(0) 人氣()

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE beans PUBLIC
  “-//SPRING/DTD BEAN/EN”
  “http://www.springframework.org/dtd/spring-beans.dtd”>

<beans>
  <bean id=”dataSource” class=”org.logicalcobwebs.proxool.ProxoolDataSource” destroy-method=”close”>
  <property name=”driver”><value>${jdbc.driver}</value></property>
  <property name=”driverUrl”><value>${jdbc.url}</value></property>
  <property name=”user”><value>${jdbc.username}</value></property>
  <property name=”password”><value>${jdbc.password}</value></property>
  <property name=”alias”><value>xfort</value></property>
  <property name=”houseKeepingTestSql”><value>SELECT 1</value></property>
  <property name=”testBeforeUse”><value>false</value></property>
  <property name=”maximumActiveTime”><value>86400000</value></property>
  <property name=”maximumConnectionCount”><value>${proxool.maximum-connection-count}</value></property>
  <property name=”delegateProperties”><value>user=${jdbc.username},password=${jdbc.password}</value></property>
</bean>

<bean id=”sessionFactory” class=”org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>
  <property name=”dataSource”><ref bean=”dataSource” /></property>
  <property name=”hibernateProperties”>
    <props>
      <prop key=”hibernate.dialect”>${hibernate.dialect}</prop>
      <prop key=”hibernate.format_sql”>true</prop>
      <prop key=”hibernate.show_sql”>false</prop>
      <prop key=”hibernate.cache.use_second_level_cache”>false</prop>
      <prop key=”hibernate.cache.provider_class”>org.hibernate.cache.EhCacheProvider</prop>
      <prop key=”hibernate.current_session_context_class”>thread</prop>
      <prop key=”hibernate.connection.release_mode”>after_transaction</prop>
      <prop key=”hibernate.transaction.factory_class”>org.hibernate.transaction.JDBCTransactionFactory</prop>
      <prop key=”hibernate.transaction.auto_close_session”>false</prop>
    </props>
  </property>
  <property name=”annotatedPackages”>
    <list>
      <value>forth.model</value>
    </list>
  </property>
  <property name=”annotatedClasses”>
    <list>
      <value>zbwei.model.ModelName</value>
    </list>
  </property>
  </bean>
</beans>

Forth 發表在 痞客邦 留言(0) 人氣()

<?xml version=”1.0″ encoding=”UTF-8″?>
<project name=”Forth” default=”compile” basedir=”.”>
  <property name=”build.dir” value=”build” />
  <property name=”build.dist.dir” value=”${build.dir}/dist” />
  <property name=”build.main.dir” value=”${build.dir}/main” />
  <property name=”build.test.dir” value=”${build.dir}/test” />
  <property name=”build.test.output.dir” value=”${build.dir}/test-output” />
  <property name=”build.test.report.dir” value=”${build.dir}/test-report” />
  <property name=”src.dir” value=”src” />
  <property name=”test.dir” value=”test” />
  <property name=”lib.dir” value=”lib” />
  <property name=”ext.dir” value=”ext” />
  <property name=”web.dir” value=”web” />

  <path id=”classpath”>
    <pathelement location=”${build.main.dir}” />
    <pathelement location=”${build.test.dir}” />
    <fileset dir=”${lib.dir}” includes=”*.jar” />
    <fileset dir=”${ext.dir}” includes=”*.jar” />
  </path>

  <target name=”prepare”>
    <mkdir dir=”${build.dist.dir}” />
    <mkdir dir=”${build.main.dir}” />
    <mkdir dir=”${build.test.dir}” />
    <mkdir dir=”${build.test.output.dir}” />
    <mkdir dir=”${build.test.report.dir}” />
  </target>

  <target name=”clean” depends=”prepare”>
    <delete dir=”${build.dir}” />
  </target>

  <target name=”compile” depends=”prepare”>
    <javac srcdir=”${src.dir}” destdir=”${build.main.dir}” encoding=”UTF-8″>
      <classpath refid=”classpath” />
    </javac>
  </target>

  <target name=”compile-test” depends=”compile”>
    <javac srcdir=”${test.dir}” destdir=”${build.test.dir}” encoding=”UTF-8″>
      <classpath refid=”classpath” />
    </javac>
  </target>

  <target name=”test” depends=”compile-test”>
    <taskdef name=”testng”
      classname=”org.testng.TestNGAntTask”
      classpath=”${ext.dir}/testng-5.1.jar” />
    <testng classpathref=”classpath”
      outputdir=”${build.test.output.dir}”
      haltOnfailure=”true”>
      <xmlfileset dir=”test” includes=”testng.xml” />
    </testng>
  </target>

  <target name=”test-report” depends=”test”>
    <junitreport todir=”${build.test.report.dir}”>
      <fileset dir=”${build.test.output.dir}” includes=”**/*.xml” />
      <report format=”noframes” todir=”${build.test.report.dir}” />
    </junitreport>
  </target>

  <target name=”pack-main” depends=”compile”>
    <jar destfile=”${build.dist.dir}/setup.jar”>
      <manifest>
        <attribute name=”Main-Class” value=”Installer” />
        <attribute name=”Class-Path” value=”. server.jar” />
      </manifest>
    </jar>
    <jar destfile=”${build.dist.dir}/server.jar”>
      <fileset dir=”${build.main.dir}” />
    </jar>
    <jar destfile=”${build.dist.dir}/web.war”>
      <fileset dir=”${web.dir}” />
    </jar>
 </target>

  <target name=”pack-test” depends=”compile-test”>
    <jar destfile=”${build.dist.dir}/test.jar”>
      <fileset dir=”${build.test.dir}” />
    </jar>
  </target>

  <target name=”dist” depends=”pack-main, pack-test”>
    <copy todir=”${build.dist.dir}”>
      <fileset dir=”.” includes=”resource/*” />
      <fileset dir=”.” includes=”config/*” />
    </copy>
  </target>
</project>

Forth 發表在 痞客邦 留言(0) 人氣()

build/dist/ - 封裝成佈署用的檔案
build/main/ - 主程式class檔
build/test/ - 測試程式class檔
build/test-output/ - TestNG輸出
build/test-report/ - JUnitReport
config/ - 設定檔
classes/ - Eclipse產生的class檔
ext/ - 其它JAR檔,例如ProGuard、yGuard
lib/ - 程式庫JAR檔
resource/ - 資源檔
src/ - 主程式原始碼
test/ - 測試程式原始碼
web/ - 網頁
web/WEB-INF/

Forth 發表在 痞客邦 留言(0) 人氣()

在Java中的Date是以long記錄時間,單位是ms,0表示1970-01-01 00:00:00 GMT,而Delphi的TDateTime則是以double記錄時間,0.0表示1899-12-30 00:00:00,整數部分代表從前述時間到某個日期所經過的天數,小數部分乘以86400代表該日經過的秒數。

從1899年12月30日到1970年1月1日,共計25569日,每日計有86400000ms,因此要把Java的時間轉成Delphi的格式可用下列程式:

static final double DAYS_BETWEEN_18991230_AND_19700101 = 25569;
static final double MILLISECONDS_PER_DAY = 86400000;

public static double javaTimeToDelphiTime(final Date time) {
    return (time.getTime() + TIME_ZONE_OFFSET_MILLIS) / MILLISECONDS_PER_DAY + DAYS_BETWEEN_18991230_AND_19700101;
}

經過計算得到的時間就可以直接給在Delphi使用。要將時間換算成Java格式可用:

public static Date delphiTimeToJavaTime(final double time) {
    return new Date((long)((time - DAYS_BETWEEN_18991230_AND_19700101) * MILLISECONDS_PER_DAY - TIME_ZONE_OFFSET_MILLIS));
}

以上就是Java的Date和Delphi的TDateTime的暴力法轉換方式。


Forth 發表在 痞客邦 留言(0) 人氣()

在命令列指定使用的keystore, client端:

java -Djavax.net.ssl.trustStore=mykeystore -Djavax.net.ssl.trustStorePassword=123456 Client

server端:

java -Djavax.net.ssl.keyStore=mykeystore -Djavax.net.ssl.keyStorePassword=123456 Server

在程式中設定使用的keystore:

char[] passphrase = "123456".toCharArray();

KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("mykeystore"), passphrase);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passphrase);

TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

// client端
Socket socket = ctx.getServerSocketFactory().createServerSocket(port);
// server端
ServerSocket serverSocket = ctx.getSocketFactory().createSocket("hostname", port);

Forth 發表在 痞客邦 留言(0) 人氣()

原本要在同一個context執行2個以上的Tapestry程式時,必須在application specification補上不少page的資訊,不過,現在有方便的做法了。檔案架構:

/app1/Home.html
/WEB-INF/app1/app1.application

/app2/Home.html
/WEB-INF/app2/app2.application

app1和app2是servlet名稱,所以在web.xml中要設定:

<servlet>
  <servlet-name>app1</servlet-name>
  <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
  <load-on-startup>0</load-on-startup>
</servlet>
<servlet>
  <servlet-name>app2</servlet-name>
  <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
  <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>app1</servlet-name>
  <url-pattern>/app1/app</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>app2</servlet-name>
  <url-pattern>/app2/app</url-pattern>
</servlet-mapping>

使用app1:http://hostname/app1/app

使用app2:http://hostname/app2/app


Forth 發表在 痞客邦 留言(0) 人氣()

1 2