文檔:http://trailblazer.demo.jboss.com/EJB3Trail/background/deploy/index.html
代碼:http://www.jboss.com/index.html?module=downloads&op=download&downloadId=41
下下來了! 跑一下看看,原來整個網站就是幫助文檔本身,有各種各樣EJB3各方面的例子。太多了,要是能找到一個簡單一點的EAR的例子就好了。~_~ 言規正轉:
The sample application in this TrailBlazer is on investment calculator. Based on your investment preference and the fund growth rate, it calculates the final payout at the end of your investment period. The calculator is bundled with this trail map and you can try it directly from the trail pages.
We will refactor the investment calculator several times to showcase how to use different technologies in the EJB 3.0 programming model
這個應用示例說的是一個investment calculator.根據你的個人投資偏好和資金的增長率,它能計算在投資期間你的支出。
然后這個investment calucator會使用EJB3.0中不同的技術進行多次重構~
這里有幾個不錯的鏈接可供收藏:
http://www.jboss.com/products/ejb3
http://docs.jboss.org/ejb3/app-server/tutorial/index.html
http://docs.jboss.org/ejb3/app-server/reference/build/reference/en/html/index.html(very good)
http://www.jcp.org/en/jsr/detail?id=220
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
http://java.sys-con.com/read/48539.htm
http://www.onjava.com/pub/a/onjava/2004/04/21/declarative.html
下下來后點build.bat然后把生成的ear拷貝到deploy目錄下,啟動JBoss,并通過http://localhost:8080/EJB3Trail訪問,
OK,第一天就結束了,下次見~
?
EAR的結構
-META-INF
?? --jboss-app.xml
?? --application.xml
-beans.jar
-web.war
第一The jboss-app.xml file defines a class loader for this application. It makes it simpler for EJB 3.0 to find the default EntityManager (see here). The content of the jboss-app.xml file is as follows.
<
jboss-app
>
??
<
loader-repository
>
trailblazer:app=ejb3
</
loader-repository
>
?
?
</
jboss-app
>
第二application.xml比較簡單:
<
application
>
??
<
display-name
>
EJB3Trail
</
display-name
>
?
??
<
description
>
J2EE?Made?Easy?Trail?Map
</
description
>
?
??
<
module
>
???
<
ejb
>
beans.jar
</
ejb
>
?
??
</
module
>
??
<
module
>
???
<
web
>
????
<
web-uri
>
web.war
</
web-uri
>
?
????
<
context-root
>
EJB3Trail
</
context-root
>
?
???
</
web
>
??
</
module
>
??
</
application
>
beans.jar的結構,主要是看persistence.xml怎么寫的
?
<
persistence
>
?
<
persistence-unit?
name
="ejb3trail"
>
??
<
jta-data-source
>
java:/DefaultDS
</
jta-data-source
>
?
?
<
properties
>
??
<
property?
name
="hibernate.hbm2ddl.auto"
?value
="create-drop"
?
/>
?
??
</
properties
>
??
</
persistence-unit
>
??
</
persistence
>
中間的properties與Hibernate本是同根生,它們的默認值可以在D:\jboss-4.0.4.GA\server\default\deploy\ejb3.deployer\META-INF\persistence.properties中找到。
這里的create-drop的意思是Hibernate會自動根據POJO和標注建表和刪除表,第一次用的時候發現該死的JBOSS把我在MySQL中建的表全部刪除了,后來趕緊把這句注釋掉~
OK,第二天就到這里。
Service object management 的優點:
Loose coupling
可以擁有不同的實現而不必修改客戶端
It only needs to know the service interface and look up the service stub object from the server using the interface name or a pre-argeed string name
Network independent
服務可以通過各種不同方式HTTP, TCP, and messaging queues提供給客戶
The client just looks up a stub of service object and call any method defined in the service interface as if it is a local call
Resource pools
服務維護對象池,客戶不必關心對象的創建,銷毀。
The client application does not need to remember to destroy objects or close connections etc
In EJB 3.0, all the managed service objects are POJOs, POJO + Anotation就是EJB3.0的編程方式。
第一SLSB, 多對一的關系
例子一是寫一個SLSB類型的inverstment caculator,然后在JSP或Swing UI中使用它的calculate服務:
步驟一
首先要定義一個接口包含所有的業務方法,這個接口是一個沒有使用annotation的POJI
public
?
interface
?Calculator?{
??
public
?
double
?calculate?(
int
?start,?
int
?end,?
????????????????
double
?growthrate,?
double
?saving);
}
步驟二
定義好接口后,然后就是EJB3實現了
@Stateless
public
?
class
?StatelessCalculator?
???????????????
implements
?Calculator,?RemoteCalculator?{
??
public
?
double
?calculate?(
int
?start,?
int
?end,?
????????????????????
double
?growthrate,?
double
?saving)?{
????
double
?tmp?
=
?Math.pow(
1
.?
+
?growthrate?
/
?
12
.,?
??????????????????????????
12
.?
*
?(end?
-
?start)?
+
?
1
);
????
return
?saving?
*
?
12
.?
*
?(tmp?
-
?
1
)?
/
?growthrate;
??}
}
這個實現很容易看懂啦,然后把它打成jar包發布到deploy下面就可以用了~
下面這段實在太精典了,忍不住多看了幾遍
Once the session bean is deployed into the EJB 3.0 container, a stub object is created and it is registered in the server's JDNI registry. The client code obtains a stub of the bean from the JNDI using its default JNDI name formatted as follows.
If the application is deployed in a EAR file, the default JNDI name is the EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local for the stub for local interface. For the remote interface (see below), it is EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local.
If the bean is deployed in a JAR file, the JNDI names are EJB-CLASS-NAME/local and EJB-CLASS-NAME/remote.
接下來是JSP,
<%
@?page?
import
=
"
trail.slsb.*,?javax.naming.*,?java.text.*
"
%>
<%!
??
private
?Calculator?cal?
=
?
null
;
??
public
?
void
?jspInit?()?{
????
try
?{
??????InitialContext?ctx?
=
?
new
?InitialContext();
??????cal?
=
?(Calculator)?ctx.lookup(
??????????????????
"
EJB3Trail/StatelessCalculator/local
"
);
????}?
catch
?(Exception?e)?{
??????e.printStackTrace?();
????}
??}
%>
<%
??String?result;
??
int
?start?
=
?
25
;
??
int
?end?
=
?
65
;
??
double
?growthrate?
=
?
0.08
;
??
double
?saving?
=
?
300.0
;
??
try
?{
????start?
=
?Integer.parseInt(request.getParameter?(
"
start
"
));
????end?
=
?Integer.parseInt(request.getParameter?(
"
end
"
));
????growthrate?
=
?Double.parseDouble(request.getParameter?(
"
growthrate
"
));
????saving?
=
?Double.parseDouble(request.getParameter?(
"
saving
"
));
????NumberFormat?nf?
=
?NumberFormat.getInstance();
????nf.setMaximumFractionDigits(
2
);
????result?
=
?nf.format(cal.calculate(start,?end,?growthrate,?saving));
??}?
catch
?(Exception?e)?{
????
//
?e.printStackTrace?();
????result?
=
?
"
Not?valid
"
;
??}
%>
<
html
>
<
body
>
<
p
>
Investment?calculator
<
br
/>
<
form?action
=
"
calculator.jsp
"
?method
=
"
POST
"
>
??Start?age?
=
?
<
input?type
=
"
text
"
?name
=
"
start
"
?value
=
"
<%=start%>
"
><
br
/>
??End?age???
=
?
<
input?type
=
"
text
"
?name
=
"
end
"
?value
=
"
<%=end%>
"
><
br
/>
??Annual?Growth?Rate?
=
?
<
input?type
=
"
text
"
?name
=
"
growthrate
"
?value
=
"
<%=growthrate%>
"
><
br
/>
??Montly?Saving?
=
?
<
input?type
=
"
text
"
?name
=
"
saving
"
?value
=
"
<%=saving%>
"
><
br
/>
??
<
input?type
=
"
submit
"
?value
=
"
Calculate
"
>
??
<
INPUT?type
=
"
button
"
?value
=
"
Close?Window
"
?onClick
=
"
window.close()
"
>
</
form
>
</
p
>
<
p
>
The?result?from?the?last?calculation:?The?balance?at?the?End?age?is
<
b
><%=
result
%></
b
></
p
>
</
body
>
</
html
>
第一個例子,不全部拷貝下來心里不舒服~
下面的東西又是比較重要的:
一個sessionbean可以同時實現local和remote接口,每種都針對一種不同的客戶,默認是local,針對在同一個JVM上調用的,比如上例
另一種是Remote,性能稍差,盡量不用。
下面是一個使用了兩個接口的session bean的例子
@Stateless
@Local?({Calculator.
class
})
@LocalBinding?(jndiBinding
=
"
EJB3Trail/LocalCalculator
"
)
@Remote?({RemoteCalculator.
class
})
@RemoteBinding?(jndiBinding
=
"
EJB3Trail/RemoteCalculator
"
)
public
?
class
?LocalRemoteCalculator?
implements
?Calculator,?RemoteCalculator?{
??
public
?
double
?calculate?(
int
?start,?
int
?end,?
???????????????????????????
double
?growthrate,?
double
?saving)?{
????
double
?tmp?
=
?Math.pow(
1
.?
+
?growthrate?
/
?
12
.,?
12
.?
*
?(end?
-
?start)?
+
?
1
);
????
return
?saving?
*
?
12
.?
*
?(tmp?
-
?
1
)?
/
?growthrate;
??}
??
public
?String?getServerInfo?()?{
????
return
?
"
This?is?the?JBoss?EJB?3.0?TrailBlazer
"
;
??}
}
@Local表示它是本地的,可以通過接口Caculator來調用
@Remote表示這是遠程的,可以通過接口RemoteCalculator來調用
@jndiBinding則表示從JNDI中如何找到它們。
也可以這樣
@Remote
public interface RemoteCalculator {
? // ... ...
}
在接口上面標注,這樣那個實現類就不用再標注~