用Hibernate建立Membership

•2008-03-20 • 發個留言
@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;
	}
}

隱形眼鏡

•2008-03-17 • 發個留言

戴了數年的眼鏡,鏡片鍍膜已經磨損、龜裂,所以下午就跑去換鏡片。等待的時候,順便問了一些隱形眼鏡的問題,本來想買日拋式,可是雙眼度數不同,要買就得買雙份,還在考慮的時候,老闆就說送我一副625度的季拋式試試看。所以,花了600元,不但換好鏡片,還得到隱形眼鏡、保養液、食鹽水。

Wicket和Spring

•2008-02-21 • 發個留言

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

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

<listener>
	</listener><listener -class>org.springframework.web.context.ContextLoaderListener</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));
			}
		}
	}
}

程式和內嵌Jetty共用spring context

•2008-02-11 • 發個留言

應用程式內嵌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();
	}
}

Maven設定Terracotta

•2008-02-11 • 發個留言

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>
					<!-- used by tc:bootjar -->
					<!-- <verbose>true -->
					<!-- <overwriteBootjar>true -->
					<!-- <bootJar>target/bootjar.jar -->

					<!-- used by tc:start and tc:stop so DSO server could outlive mvn process -->
					<!-- <startServer>true -->
					<!-- <spawnServer>true -->
					<!-- <config>${basedir}/tc-config.xml -->
					<!-- <jvm>C:\jdk1.6.0\bin\java.exe -->
					<!-- <jvmargs>-Xmx20m -->
				</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好用多了。

blog救援完畢

•2008-02-08 • 發個留言

全靠Wayback MachineGoogle,花了7個小時剪剪貼貼之後,總共救回117篇文章。

server被偷

•2008-02-08 • 發個留言

放在遙遠的樓梯間機房裡的server在除夕夜9:38斷線,10點多趕到時,發現攝影機被破壞,樓梯間鐵門被撬開,機房裡的server和監視器主機都消失了。已經工作七年的server配備Intel Pentium III 700MHz CPU、512MB RAM、160GB HDD,上面運行著bento.tw、cert.tw、ruby.tw、zbwei.net,不但有email、blog、wiki、forum、電子書,最重要的是,還有大家都喜歡的神秘圖片。目前正在靠archive.org和google慢慢整裡公開的blog和wiki內容,其餘的資料就安心上路吧!blog暫時搬到http://forth.wordpress.com/,FeedBurner亦已修改至新位置。

Apple IIc開箱照

•2008-02-05 • 發個留言

沒想到在2008年竟然能看見Apple IIc開箱照,能從1988年5月5日完整保存至今,實在太神奇了。eBay才真的是什麼都有、什麼都賣、什麼都不奇怪。

Java調用Ruby物件

•2008-02-01 • 發個留言

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();
	}
}

常用的ruby程式庫

•2007-12-27 • 發個留言
  • rails
  • mongrel
  • mongrel_cluster
  • acts_as_cached
  • acts_as_ferret
  • capistrano
  • fcgi
  • gettext
  • sqlite3-ruby
  • mechanize
  • ruby-net-ldap
  • ruby-openid
  • sendfile
  • log4r
  • rspec
  • ZenTest