Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

11/15/2013

[Alfresco] ลองทำ Web Service ด้วย Java

Alfresco มีช่องทางในการที่ให้เราสร้าง Web Service ขึ้นมาได้โดยใช้ความสามารถของ Spring Surf ซึ่ง Alfresco เราสามารถสร้างได้โดยเลือกระหว่าง 2 ภาษาคือ JavaScript ซึ่งใช้ Rhino Library ของ Mozilla เหมาะสำหรับงานที่ไม่มีความซับซ้อนมากมายอะไร และ Java สำหรับงานที่ซับซ้อนมาก

6/07/2012

JavaScript Note #1 : เขียนเทียบกับ Java

ผมเป็นคนเขียน javascript ไม่เป็นเลย ถ้าแค่เขียนแบบงูๆ ปลาๆ เช่น เขียนกับ jQuery ก็พอได้ (ทำแบบนี้ใน zk บ่อย) แต่ตอนนี้มีงานที่ต้องอาศัย javascript แล้ว ไม่รู้มันจริงๆ จังๆ ก็คงไม่ได้ซะด้วย เลยนั่งคิดว่าจะทำยังไงดีน้อ เอาวะเขียนเทียบกับภาษาที่ตัวเองถนัดสุด สำหรับผมมันก็คือ java นั้นเอง

เรื่องของ class

เนื่องจากใน javascript มันไม่มี keyword class ให้เห็นเลย ทุกอย่างเป็น function เพราะฉะนั้น javascript จะใช้วิธีทำ function constructor เอา เมื่อลองเขียนกับ java ที่มันเป็น class-base ต้องขึ้น class ก่อนเลยจะได้ประมาณนี้

javascript javascript (compile from coffeescript) java
function Employee() { this.name = ""; this.dept = "general"; }
var Employee; Employee = (function() { function Employee() { this.name = ""; this.dept = "general"; } return Employee; })();
class Employee { private String name; private String dept; public Employee() { this.name = ""; this.dept = "general"; } }

เนื่องจากว่า javascript เป็น dynamic typing มันเลยไม่ต้องกำหนด type ก่อนและมันไม่มีเรื่องของการเข้าถึง (access modifier) เลยไม่ต้องกำหนดเหมือน java ส่วนการสร้าง instance นั้นก็จะทำได้เหมือนกับ java เลยโดยการใช้ keyword "new" และที่น่าสนใจอีกเรื่อง ซึ่งอาจารย์ชาญวิทย์ แก้วกสิ (@chanwit) เป็นคนแนะนำมาโดยการใช้ coffeescript compile ให้ได้ javascript ก็ทำให้รู้ว่าเราสามารถเขียน javascript แล้ว new object ได้หน้าตาเหมือนกันก็ได้

source coffeescript:

class Employee 
  constructor: ->
    @name = ""
    @dept = "general"

การ inheritance และ subclass

การทำ inheritance ใน javascript นั้นเป็นแบบ prototype base โดยทุก class function (เค้าเรียกอย่างนี้หรือป่าว) จะมี property ชื่อ prototype โดยเราจะทำการกำหนด object ให้กับ property prototype เพื่อบอกให้รู้ว่า extends มาจาก class อะไร (ใน javascript  นั้นเราจะใช้ทุกอย่างเป็น object ทั้งหมด) แต่ใน java ซึ่งเป็น class base นั้นจะใช่ keyword extends แทน 



javascript java
function WorkerBee(name, dept, projects) { this.base = Employee; this.base(name, dept); this.projects = projects || []; } WorkerBee.prototype = new Employee;
class WorkerBee extends Employee { private String[] projects; public WorkerBee(String name, String dept, String[] projects) { super(name, dept); this.projects = projects; } }
สังเกตได้ว่าจากข้างโค้ด java ข้างบนจะเห็นว่าผมได้สั่ง super เพื่อที่จะส่งค่าพวกนี้ไปให้ class แม่ ใน javascript นั้นจะใช้ตัวแปรนึงเก็บ function ของ class แม่เอาไว้แล้วก็ส่งค่าไปให้ตามนั้น [เอาไว้แค่นี้ก่อนเดี๋ยวจะกลับมาแก้]

5/16/2012

สร้าง folder ที่เหมือนกันในแต่ล่ะ directory

ตอนสร้าง directory ของ java มักจะเป็น

.
└── src
    ├── main
    │   └── java
    └── test
        └── java

สังเกตว่าต้อง mkdir ทีล่ะ folder ตายแน่ๆ ถ้ามีแบบนี้เยอะๆ เลยหาวิธีดูปรากฎว่า mkdir สามารถสร้างได้ในคำสั่งเดียวคือใช้ {} ครอบที่จะให้สร้างใน folder นั้นๆ

mkdir -p src/{main,test}/java

ก็จะออกมาเช่นเดียวกับ directory hierachy ข้างบน

2/02/2012

ลง groovy

ช่วงนี้ฝึกงาน ได้มีโอกาสเขียนภาษา Groovy ซึ่งเป็นภาษาที่รันบน JVM (Java Virtual Machine) ใช้ class ร่วมกับ Java ได้ รองรับทั้ง Dynamic และ Static Type (จริงๆแล้ว Groovy เป็นภาษา Dynamic) ส่วนหน้าตา Syntax ของภาษามันก็ช่างละม้ายคล้าย Ruby ยิ่งนัก เอาล่ะพล่ามกันมาพอหอมปากหอมคอแล้ว มาลองดุวิธีลงกันบ้างดีกว่า

เริ่มแรกเลยไปเอา binary จาก http://groovy.codehaus.org/Download ถ้าเครื่องใครเป็น Windows ก็โหลดที่เป็น Windows-Installer มา หรือถ้าเป็นตระกูล Unix(Linux, MacOSX) ก็โหลดแบบ binary มาใช้ หรือว่าใครอยากแกะ sourcecode ทาง Groovy เองก็มีให้โหลด sourcecode เหมือนกัน :)

หลังจากนั้นใครใช้ Windows-Installer ก็ double click  next next next ไปตามเรื่องตามราว ส่วนของ ตระกูล Unix นั้นแตก .zip ออกมาก็เรียกใช้ได้เลย 

ส่วนต่อมาคือการเซต path ให้ Groovy ทำงานได้โดย Groovy เองบังคับให้เซต JAVA_HOME ก่อน (ที่เก็บ JDK) และต้องเซต GROOVY_HOME ซึ่งเป็นที่เก็บ ไฟล์ของ Groovy นั้นเอง โดย

$ export GROOVY_HOME=path/to/groovy
$ export PATH=$GROOVY_HOME/bin:$PATH

ของ Windows นั้นสามารถไปศึกษาวิธีเซต Path เองได้ขอแค่ให้เซต Variable ตามข้างบน (จริงๆ อยากเอามาให้ดู แต่ไม่มี Windows)

เท่านี้คุณก็สามารถใช้ groovy ได้อย่างสบายใจแล้ว :)

1/06/2012

การ mapping resources ที่ใช้เก็บ script ต่างๆ

ตอนแรก map script ด้วย

<resources "="" mapping="/resources/** location=" resources=""></resources>
ปรากฎว่าเมื่อสั่ง mvn tomcat:run แล้วกลับเจอ tomcat มันคาย Exception ออกมา

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 14 in XML document from ServletContext resource [/WEB-INF/spring/appServlet/servlet-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'resources'. One of '{"http://www.springframework.org/schema/beans":import, "http://www.springframework.org/schema/beans":alias, "http://www.springframework.org/schema/beans":bean, WC[##other:"http://www.springframework.org/schema/beans"], "http://www.springframework.org/schema/beans":beans}' is expected.
 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
 at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
 at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
 at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
 at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:131)
 at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:522)
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:436)
 at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
 at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
 at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
 at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
 at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
 at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
 at javax.servlet.GenericServlet.init(GenericServlet.java:212)
 at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
 at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
 at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4350)
 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4659)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
 at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
 at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
 at org.apache.catalina.startup.Embedded.start(Embedded.java:825)
 at org.codehaus.mojo.tomcat.AbstractRunMojo.startContainer(AbstractRunMojo.java:558)
 at org.codehaus.mojo.tomcat.AbstractRunMojo.execute(AbstractRunMojo.java:255)
 at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
 at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
 at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
 at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
 at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
 at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
 at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
 at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
 at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
 at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
 at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
 at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
 at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
 at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
 at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
 at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
ทางออกของปัญหาก็แก้ด้วยการใช้ mvc namespaces แทน
<mvc:resources mapping="/resources/**" location="/resources/" />

เท่านี้ปัญหาก็หมดไป :)