5.1. Application定义
下图是我们要实现的application
图5_1
这个只有一层composite, 命名为 restaurant,
它包含5个component
RestaurantServiceComponent
显示餐馆菜单
结帐账单.
MenuServiceComponent
提供菜单名字和价格.
BillServiceComponent
计算账单,包括消费税和小费.
VATServiceComponent
计算包含消费税的账单价格.
TipServiceComponent
计算小费的价格.
5.2. 过程
5.2.1. 创建一个java project
Ø 选择菜单 【New > Java Project】.
Ø Project 名字为"Restaurant2". 选择 “Create separate folders for sources and class files”,点击next
Ø 在Libraries里面,添加User Library TUSCANY
图5_2
Ø 点击”next”和”finish”.
5.3. 创建SCA Composite diagram
Ø 在project上右键,选择 【New > Other....】
Ø 在SCA目录下,选择 SCA Composite Diagram,点击next
图5_3
Ø 文件名字设为Restaurant2.composite_diagram,点击 Finish.
完成后SCA Composite Designer自动打开新创建的文件. 在diagram上右键,选择Show Properties 来打开Properties view
图5_4
5.4. 添加component
使用palette创建component
图5_5
图5_6
填入RestaurantServiceComponent作为component的名字。同样创建其他的compoent,MenuServiceComponent, BillServiceComponent, VatServiceComponent, and TipServiceComponent.
图5_7
5.5. 添加Service
有两种方式给component添加service
一个是使用palette,在palette上选择service,然后在要添加的component上点一下,一个service就添加到component上
第二个方法是把鼠标移到component上,一个工具条自动就出现,选择绿色的那个。
图5_8
*在 RestaurantServiceComponent上添加 RestaurantService,
*在MenuServiceComponent上添加MenuService,
*在BillServiceComponent上添加BillService,
*在VatServiceComponent上添加VatService,
*在TipServiceComponent上添加TipService.
图5_9
5.6. 添加References
类似方法给component添加reference
* 在RestaurantServiceComponent上添加menuService,
* 在RestaurantServiceComponent上添加billService,
* 在BillServiceComponent上添加vatService,
* 在BillServiceComponent上添加tipService
图5_10
5.7. wire reference到service
有palette上的wire把reference和service连起来
RestaurantServiceComponent上的reference(menuService)连到MenuServiceComponent的service(MenuService),以此类推,把所有reference都连到相应service
图5_11
5.8. Promote service
把RestaurantServiceComponent上的serivce(RestaurantService)promote到composite层,这样外面就可以调用这个application提供的功能。
在RestaurantService绿色图标上右键,选择promot
图5_12
5.9. 用SCA Composite Model Editor打开Restaurant2.comosite,在Restaurant2.comosite 右键选open with
图5_13
用Text Editor打开
图5_14
可以在这两个editor里编辑composite,会自动同步
5.10. 给service定义java interface
把鼠标移到RestaurantServiceComponent上的service上,会自动有一个工具条出现,选择add JavaInterface
图5_15
选中新添加的JavaInterface图标, 在properties中设置Interface的类名,包括package,restaurant2.api.RestaurantService
图5_16
以此类推给所有service添加JavaInterface
名字分别为restaurant2.api.MenuService
restaurant2.api.BillService
restaurant2.api.VatService
restaurant2.api.TipService
图5_17
5.11. 给component定义java implementation class的名字
鼠标移到RestaurantServiceComponent上,会自动有一个工具条出现,选择add JavaImplementation
图5_18
选中新添加的JavaImplementation图标, 在properties中设置class,包括package,restaurant2.lib.RestaurantServiceImpl
图5_19
以此类推,给所有component添加JavaImplementation, 类名分别为
restaurant2.lib.MenuServiceImpl
restaurant2.lib.BillServiceImpl
restaurant2.lib.VatServiceImpl
restaurant2.lib.TipServiceImpl
图5_20
5.12. 生成代码框架
首先在project上右键选择 Add SCA Nature
图5_21
然后在Restaurant2.composite上右键 选择SCA>Generate Java Skeleton…
图5_22
出现确认窗口,点ok
图5_23
生成后项目结构是
图5_24
生成的代码只有一个空壳,要在里面添加方法定义和实现。生成的代码的样子
5.13. 接口类的定义
- Restaurant Service
- package restaurant2.api;
-
- public interface RestaurantService {
- Menu[] getMenus();
- double getBill(Menu menu);
- }
- Menu Service
- package restaurant2.api;
-
- public interface MenuService {
- Menu[] getMenu();
- double getPrice(Menu menu);
- }
- Bill Service
- package restaurant2.api;
-
- public interface BillService {
- double getBill(double menuPrice);
- }
- Vat Service
- package restaurant2.api;
-
- public interface VatService {
- double getPriceWithVat(double price);
- }
- Tip Service
- package restaurant2.api;
-
- public interface TipService {
- double getPriceWithTip(double price);
- }
添加DTO Menu:
- package restaurant2.api;
- import java.io.Serializable;
- public class Menu implements Serializable{
- private int id;
- private String details;
- public Menu(){}
- public Menu(int idC, String detailsC) {
- this.id = idC;
- this.details = detailsC;
- }
- public String printMenu() {
- return this.details;
- }
- public int getId() {
- return this.id;
- }
- public String getDetails() {
- return details;
- }
- public void setDetails(String details) {
- this.details = details;
- }
- public void setId(int id) {
- this.id = id;
- }
- }
5.14. 实现类
- Restaurant Service
- package restaurant2.lib;
-
- import org.osoa.sca.annotations.Reference;
- import org.osoa.sca.annotations.Service;
-
- import restaurant2.api.BillService;
- import restaurant2.api.Menu;
- import restaurant2.api.MenuService;
- import restaurant2.api.RestaurantService;
-
- @Service(RestaurantService.class)
- public class RestaurantServiceImpl implements RestaurantService {
-
- private MenuService menuService;
- private BillService billService;
-
- @Reference
- public void setMenuService(MenuService menuService) {
- this.menuService = menuService;
- }
-
- @Reference
- public void setBillService(BillService billService) {
- this.billService = billService;
- }
-
- public double getBill(Menu menu) {
- double menuPrice = this.menuService.getPrice(menu);
- return this.billService.getBill(menuPrice);
- }
-
- public Menu[] getMenus() {
- return this.menuService.getMenu();
- }
- }
- Menu Service
- Bill service
- package restaurant2.lib;
-
- import org.osoa.sca.annotations.Reference;
- import org.osoa.sca.annotations.Service;
-
- import restaurant2.api.BillService;
- import restaurant2.api.TipService;
- import restaurant2.api.VatService;
-
- @Service(BillService.class)
- public class BillServiceImpl implements BillService {
-
- private VatService vatService;
- private TipService tipService;
-
- @Reference
- public void setVatService(VatService vatService) {
- this.vatService = vatService;
- }
-
- @Reference
- public void setTipService(TipService tipService) {
- this.tipService = tipService;
- }
-
- public double getBill(double menuPrice) {
- double pricewithTaxRate =
- this.vatService.getPriceWithVat(menuPrice);
- double priceWithTipRate =
- this.tipService.getPriceWithTip(pricewithTaxRate);
- return priceWithTipRate;
- }
- }
- Vat Service
- Tip service
5.15. 测试 Restaurant
创建一个新的测试类 Client。这个client会把Restaurant2发布到tuscany里面,然后调用promote出来的那个service的interface。
5.16. 运行client:
在class Client上右键选择【Run as > Java Application】
运行结果为
图5_25
到此一个简单的application就开发完了。后面会使用这个例子,结合SCA里面的概念仔细说明
- package test;
- import org.apache.tuscany.sca.host.embedded.SCADomain;
- import restaurant2.api.Menu;
- import restaurant2.api.RestaurantService;
- public class Client {
- public static void main(String[] args) throws Exception {
- SCADomain scaDomain = SCADomain.newInstance("Restaurant2.composite");
- RestaurantService restaurantService = scaDomain.getService(
- RestaurantService.class, "RestaurantServiceComponent");
- Menu[] menus = restaurantService.getMenus();
- System.out.println("--- Menu ---");
- for (Menu m : menus) {
- System.out.println("- " + m.printMenu());
- }
- System.out.println();
- Menu menu = menus[3];
- System.out.println("My choice: " + menu.printMenu());
- System.out.println();
- double price = restaurantService.getBill(menu);
- System.out.println("Price (" + menu.printMenu() + "): " + price);
- scaDomain.close();
- }
- }
- package restaurant2.lib;
- import org.osoa.sca.annotations.Property;
- import org.osoa.sca.annotations.Service;
- import restaurant2.api.TipService;
- @Service(TipService.class)
- public class TipServiceImpl implements TipService {
- @Property
- public double tipRate;
- public TipServiceImpl(){
- this.tipRate=10;
- }
- public double getPriceWithTip(double price) {
- return price * this.tipRate/100 + price;
- }
- }
- package restaurant2.lib;
- import org.osoa.sca.annotations.Service;
- import restaurant2.api.VatService;
- @Service(VatService.class)
- public class VatServiceImpl implements VatService {
- public double vatRate;
- public VatServiceImpl(){
- this.vatRate=19.6;
- }
- public double getPriceWithVat(double price) {
- return price * this.vatRate/100 + price;
- }
- }
- package restaurant2.lib;
- import org.osoa.sca.annotations.Init;
- import org.osoa.sca.annotations.Service;
- import restaurant2.api.Menu;
- import restaurant2.api.MenuService;
- @Service(MenuService.class)
- public class MenuServiceImpl implements MenuService {
- private Menu[] menus;
- private double[] prices;
- @Init
- public void init() {
- this.menus = new Menu[] {
- new Menu(0, "Grilled hamburger with French fries" ),
- new Menu(1, "Roasted chicken with vegetables"),
- new Menu(2, "Duck breast in an orange sauce"),
- new Menu(3, "Duck foie gras & mango chutney") };
- this.prices = new double[] { 10, 15, 35, 50 };
- }
- public Menu[] getMenu() {
- return this.menus;
- }
- public double getPrice(Menu menu) {
- return this.prices[((Menu) menu).getId()];
- }
- }
- public double getPrice(Menu menu) {
- return this.prices[((MenuImpl) menu).getId()];
- }
- }
- /*
- * Generated from Restaurant2.composite on 06/17/10 at 16:37:42.
- */
- package restaurant2.api;
- import org.osoa.sca.annotations.Remotable;
- @Remotable
- public interface BillService {
- // TODO: add the service operations.
- }