2011年10月21日星期五

JavaEE_008:JavaEE6 新特性之二:JPA2.0

与JPA1.0最大的不同是,JPA2.0已经从EJB中脱离出来,形成自己的规范:JSR-317。
也就是说关于数据的持久化层的标准,O-R Mapping的标准,完全由JPA2.0来制定,以前的EJB Entity Bean被废除。
JPA2.0的特性如下:

1. 映射功能增强
(1)Collection of embeddables and basic types
不只是JPA entities的Collection。
可以有多层嵌套。
Collection of embeddables 举例:
@Embeddable public class BookReference {
String title;
Float price;
String description;
String isbn;
Integer nbOfPage;
...
}

@Entity public class ListOfGreatBooks {
@ElementCollection
protected Set javaBooks;
...
}

(2)支持“更加灵活”的Maps
Keys或values可以是entities,也可以是embeddables或basic types。

(3)更多的关联关系映射选项
支持map 的单向 one-to-many 关联(JPA1.0 只允许双向 one-to-many关联)。

2. Richer JPQL
提供类似于 SQL 的 CASE, NULLIF,COALESCE 等函数。

3. Criteria API
(1)应广大开发者要求增加了 Criteria API,是一种完全面向对象的查询方式。
(2)与JPQL面向String不同,Criteria API完全面向对象,因此是一种强类型的API。
(3)JPQL在运行时解析语句,所以可能抛出运行时异常,与JPQL不同,Criteria API在编译时就能检查出错误。
(4)Criteria API能够操作the meta-model,访问Persistence Unit。
动态: EntityManager.getMetamodel()。
静态: 每一个entity X 都对应一个metamodel class X_。
(5)CriteriaQuery as a query graph。

面向对象的Criteria API查询方式举例:
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Book> query =cb.createQuery(Book.class);
Root<Book> book = query.from(Book.class);
query.select(book).where(cb.equal(book.get("description"), ""));

相当于SQL语句:
SELECT b FROM Book b WHERE b.description IS EMPTY

类型安全的Criteria API查询方式举例:
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Book> query =cb.createQuery(Book.class);
Root<Book> book = query.from(Book.class);
query.select(book).where(cb.isEmpty(book.get(Book_.description)));
这里的Book_类是由JPA2.0 MetaModel自动生成的。

4. 规范了persistence.xml中可以设置的JDBC properties
在persistence.xml 文件中可以设置的属性如下:
javax.persistence.jdbc.driver
javax.persistence.jdbc.url
javax.persistence.jdbc.user
javax.persistence.jdbc.password
javax.persistence.lock.scope
javax.persistence.lock.timeout

5. 二级缓存
(1)entities增加元注释@Cacheable
(2)contain(Class,PK), evict(Class,PK), ...

6. 支持悲观锁
JPA2.0增加支持悲观锁(JPA1.0 只支持乐观锁)。

7. detach()

8. Join, ListJoin, MapJoin

9. Orphan removal functionality
@OneToMany(orphanRemoval=true)

10. BeanValidation integration on lifecycle

参考文献:
1. http://developer.51cto.com/art/200906/130976.htm
2. http://jcp.org/en/jsr/detail?id=317

JavaEE_007:JavaEE6 新特性之一:EJB3.1

1. 无需Local Interface,Remote Interface可根据需要选择
POJO类 + 元注释 = EJB。例如:
@Stateless
public class HelloBean {
public String sayHello() {
String message = “hello");
return message;
}
}

取消Local Interface的原因是因为本地其它模块在调用该EJB时,需要细粒度访问该EJB。
这样的话,与其定义一个Local Interface暴露一大堆细粒度方法,不如让本地其它模块直接访问该类。
而Remote Interface一般是粗粒度调用,所以不必暴露那些细粒度的方法。

使用依赖注入的方式调用EJB,引用类型就是POJO类。例如:
@EJB private HelloBean helloBean;
...
String msg = helloBean.sayHello();

2. 增加单例模式的Session EJB
Singleton Session EJB 确保在一个JVM中只有一个EJB实例。
可以用来在应用中共享状态。例如:
@Singleton
public class CachingBean {

private Map cache;

@PostConstruct void init() {
cache = ...;
}

public Map getCache() {
return cache;
}

public void addToCache(Object key, Object val) {
cache.put(key, val);
}
}

默认情况下,EJB容器保证Singleton Session EJB是线程安全的,即同一时刻只允许一个线程访问该EJB,其它线程将被阻塞。
如果想要允许并发Singleton Session EJB,需要增加@ConcurrencyManagement元注释。

3. 支持异步调用Session Bean 方法
EJB容器为了让EJB的行为可控,不允许编写多线程的EJB,因为可能会引起无法预料的异常情况。
所以以前的EJB方法都是同步的,当然你可以使用Message Driven Bean来达到异步通信的目的。
但毕竟Message Driven Bean需要配置其它资源如Queue/Topic,并且需要实现其指定的Interface。
现在好了,你可以通过在EJB方法上增加@Asynchronous,就可以异步的调用该方法了。例如:

@Stateless
public class OrderBean {

public void createOrder() {
Order order = persistOrder();
sendEmail(order); // fire and forget
}

public Order persistOrder() {...}

@Asynchronous
public void sendEmail(Order order) {...}
}

异步方法可以返回一个java.util.concurrent.Future,Future对象容纳了异步操作返回的结果。
你可以访问Future对象,通过get()方法获取返回值、捕捉异常、取消该异步调用。
你也可以其它类型的返回值,如AsyncResult,它实现了Future接口。例如:
@Stateless
Public class CalculatorBean implements CalculatorService {

@Asynchronous
public Future performCalculation(...) {
// ... do calculation
Integer result = ...;
return new AsyncResult(result);
}
}

思考:异步调用Session Bean 方法的原理是怎样的?

4. 简化EJB打包规则:EJB可以直接打进.war包中
EJB不必再打进ejb jar包中,可以直接打进.war包中。
这意味着你可以将EJB类放到WEB-INF/classes目录下,或者放到WEB-INF/lib目录下的一个.jar文件中。
EJB部署描述符也是可选的,如果你需要它,你可以将EJB部署描述符打包到WEB-INF/ejb-jar.xml文件中。


思考:部署描述符和元注释哪个优先级高?

5. 增强Timer Service
提供了类似Cron语法的Schedule定义。例如:
second [0..59], minute[0..59], hour[0..23]...
dayOfMonth[1..31]
dayOfWeek[0..7] or [sun, mon, tue..]
Month[0..12] or [jan,feb..]

@Stateless
public class WakeUpBean {

@Schedule(dayOfWeek="Mon-Fri", hour="9")
void wakeUp() {
...
}
}

思考:EJB Timer Service与Quartz相比,优势在哪里?

6. 提供轻量级EJB:EJB Lite
EJB毕竟是一个“很重”的服务器端组件,很多应用实际用不到EJB完整的功能。
为此,EJB 3.1中提供了一个轻量级EJB:EJB Lite,它是EJB API的一个子集。
EJB3.1 与 EJB Lite的功能对比如下图。

EJB Lite提供了厂商选项,让各大应用服务器厂商可以定制化实现自己的EJB Lite。
使用EJB Lite开发的应用同样可以部署到任何支持EJB的服务器上。

7. Portable JNDI Name
在Java EE 6之前,不同厂商对JNDI 的命名方法各不相同,给开发人员造成了一些不便。
为此,JavaEE6规范了JNDI的路径语法如下:
java:global[/]//
java:app[/]/
java:module/
其中,global :全局可见;app:同一个应用可见;module:同一个应用模块可见。
因此,开发JavaEE6应用时,请遵守新的JNDI命名规范。

Portable JNDI name举例:
(1)Client inside a container (use DI)
@EJB Hello h;
(2)Client outside a container
Context ctx = new InitialContext();
Hello h = (Hello) ctx.lookup(xyz);
(3)Portable JNDI name is specified
java:global/foo/bar/HelloEJB

8. Embeddable EJB Container
允许在JavaSE中创建EJB Container,也就是说,不用把EJB部署到应用服务器就可以测试EJB。
此时JavaSE客户端和EJB在相同的JVM中运行,如下图所示。

这为测试,批处理过程和在桌面应用程序中使用EJB提供了很大的方便。
public static void main(String[] args){
EJBContainer container = EJBContainer.createEJBContainer();
Context context = container.getContext();
Hello h = (Hello)context.lookup("Global_JNDI_Name");
h.sayHello();
container.close();
}

9. Interceptors and InterceptorBinding

10. Singletons can be chained

11. Non persistent timer

12. @StatefulTimeout

参考文献:
1. http://11643599.blog.hexun.com/55545584_d.html
2. http://developer.51cto.com/art/201001/179588.htm
3. http://developer.51cto.com/art/200907/138734.htm
4. http://developer.51cto.com/art/200906/127156.htm
5. http://javahowto.blogspot.com/2010/11/programmatically-bind-global-jndi.html
6. http://www.ofmclub.com/content/java-ee-6%E4%B8%AD%E6%96%B0%E5%A2%9E%E7%9A%84jndi%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4

2011年10月18日星期二

Tips_012:开机后,如何自动登录Win7?

方法如下:
1. 运行regedit。
2. 找到HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\winlogon
3. 找到属性AutoAdminLogon,设置为1。(0关,1开)
4. 找到属性DefaultPassword,设置为你的开机密码。
5. 其它属性如DefaultDomainName,可根据情况设置。

设置完毕后,重启机器,应该能够自动进入Win7,这样可以省一些时间。

参考文献:
1. http://www.computerperformance.co.uk/windows7/windows7_auto_login.htm

2011年10月12日星期三

JDev_030:JDeveloper实验中常用的SQL命令

在使用JDeveloper做实验的过程中,经常会与数据库打交道,这里总结一下常用的SQL命令:

  1. 以DBA身份进入数据库
    sqlplus sys/welcome1@XE as sysdba

  2. 以DBA身份连接数据库
    connect sys/welcome1 as sysdba;

  3. 以system用户登录,给HR Schema解锁,做有关HR Schema的实验需要设置此项。
    alter user HR identified by HR account unlock;


  4. 做实验时,如果没有HR Schema可以从其他人的机器上导出再导入。
    先在别人的机器上导出:exp system/welcome1@XE file=C:\Temp\hr.dmp owner=(hr)
    再导入到自己的机器上(这里用HR_COPY来区分,所以需要先创建HR_COPY Schema):
    grant connect, resource to hr_copy identified by hr_copy;
    imp system/welcome1 file=hr.dmp log=hr.log fromuser=hr touser=hr_copy
    下载:hr.dmp

  5. 修改seesions,安装SOA Suite,WebCenter Suite需要设置此项。
    alter system reset sessions scope=spfile sid='*';

  6. 修改processes,安装SOA Suite,WebCenter Suite需要设置此项。
    alter system set processes=500 scope=spfile;

  7. 查看连接数据库的Session详细信息
    SELECT SYS_CONTEXT('USERENV','TERMINAL') TERMINAL,SYS_CONTEXT('USERENV','HOST') HOST,SYS_CONTEXT('USERENV','OS_USER') OS_USER,SYS_CONTEXT('USERENV','IP_ADDRESS') IP_ADDRESS FROM DUAL;
    或 SELECT utl_inaddr.get_host_address(host_name), host_name FROM v$instance;

  8. 获取数据库的Session数量
    conn sys/welcome1 as sysdba;
    select count(sid),username from v$session group by username;

  9. 根据已有Table创建新Table
    create table JOBS_CheckBox as select * from Jobs;
    ALTER TABLE JOBS_CHECKBOX ADD (IS_Parttime VARCHAR2(1) );
    ALTER TABLE JOBS_CHECKBOX ADD CONSTRAINT JOBS_CHECKBOX_PK PRIMARY KEY ( JOB_ID )ENABLE;

  10. 创建HR Schema的SQL脚本human_resources.zip
     
  11. 查看SID         
    select instance_name from v$instance;

2011年10月11日星期二

JDev_029:JDeveloper 11g 问与答

问题1:发布含有ADF的Web应用时,报告失败,错误信息如下:
weblogic.application.ModuleException: Failed to load webapp: 'HelloClientADF.war' ...... java.lang.ClassNotFoundException: oracle.adf.model.servlet.ADFBindingFilter ......


答:首先要确认WebLogic Server是否已经安装了ADF Runtime Libary。(具体方法参见《图解安装WebLogic 10gR3 (支持ADF)》)。
然后创建两个Deployment Profiles:一个用于war,一个用于ear(包含war)。
在ear profile中的weblogic-application.xml包含ADF libary的指向。
发布ear应用,发布成功后,你会在WebLogic Console 中看到ADF libary 中有一个reference:即你刚刚发布的ear应用。
参考文献:
1. http://biemond.blogspot.com/2008/12/deploy-your-11g-webapp-to-weblogic.html

问题2:如何自定义快捷键。

答:Tools-->Preferences-->Shortcut Keys


问题3:安装Apple的Safari浏览器后,发现无法启动JDeveloper内嵌的WebLogic Server,错误信息如下:
*** Using port 7101 ***

[waiting for the server to complete its initialization...]
\QuickTime\QTSystem\QTJava.zip was unexpected at this time.
Process exited.


答:检查ClassPath,发现多了…\QuickTime\QTSystem\QTJava.zip,去掉之后,启动正常了。

问题4:如何查看JDeveloper本身的日志?

答:找到目录[jdev_home]\jdev\bin,启动jdev.exe或jdev64.exe,而不是默认的jdevW.exe或jdev64W.exe。
这样会启动JDeveloper时,会同时启动一个Dos Console,JDeveloper的日志会在其中输出。

问题5:如何修改JDeveloper内嵌的WebLogic Server使用的内存大小?

答:找到JDeveloper的运行目录,比如C:\Oracle\JDevRuntime\system11.1.2.2.39.61.83.1\DefaultDomain\bin。
打开startWeblogic.cmd,在行“@REM Call setDomainEnv here.”之前增加一行内容如下:
set USER_MEM_ARGS=-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m
重启启动内嵌的WebLogic Server,会发现输出了一行内容:
JAVA Memory arguments: -Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m
说明内存设置成功。

问题6:如何让JSP/JSF页面默认的打开编辑模式是Source?


答:JSP/JSF默认的打开编辑模式是Design,如果页面内容很多,打开时要Load半天,让人很着急。那么如何把JSP/JSF默认的打开编辑模式改成Source呢?

打开Tools --> Preferences --> File Types,点击Default Editor页签,选择Web Pages,我这里只选择了JSP,修改其默认的打开编辑模式为Source。


参考文献:
1. http://bexhuff.com/2012/09/jdeveloper-memory-and-performance

问题7:BPM/SOA Server运行正常,但JDeveloper就是连接不上BPM/SOA Server怎么回事?

答:检查一下Web Browser and Proxy设置,确认没有勾上“Use HTTP Proxy Server”。
别忘了重启JDeveloper。


参考文献:
1. http://www.javaservletsjspweb.in/2013/01/changing-default-browser-with.html#.UjbyncbEeKI

JDev_028:使用JDeveloper开发WebService之六:RESTFul

开发环境:JDeveloper 11.1.2.1.0。
完成《Integrating RESTFul Web Services》。

实验导读:
在WebService的世界中,REpresentational State Transfer (REST) 正越来越受重视。
REST把所有URLs都看做资源(Resouces),资源无外乎增删改查这四种操作。
而HTTP方法:PUT、GET、POST、Delete恰好对应Create、Read、Update、Delete (CRUD)操作。
因此就用HTTP的这些方法就可以对资源进行所有的操作。
网络上的所有资源都可以用统一的方法来访问和操作,这个想法如果能够实现该是多么美好!

REST并不是一个标准,而是一种被推荐的Web应用架构。
REST只是利用Web应用中现有的标准,构成自己的架构体系。
这些标准其实大家都耳熟能详:HTTP、URL、URI、XML、HTML、image、video、Resource Types和MIME Types。

REST风格的架构包括Client和Server两部分,特别是无状态的Client和Server。
并不是一个标准,而是一种被推荐的Web应用架构。

Client发送请求到Server,Server处理请求并返回响应到Client。
从本质上讲,请求和响应不过是同一资源的不同表现形式。
资源可以是任何有意义的东东。
所谓表现形式是资源在某种状态下的呈现内容,比如一个XML文档。
无论在何时,Client要么处在请求资源的状态之中,要么就在“休息”之中。
这和我们访问页面的行为是一致的,要么我们发起一个请求等待响应,要么我们什么也不做。
在REST看来,Client发送请求时,资源是从一个状态转换成到另一个状态。

REST最初是基于HTTP,但实际上并不局限于该协议。
正如前面介绍的,REST是一种架构,可以用于其它应用层协议。
只要这些应用层协议提供了丰富的状态转换字典,比如HTTP协议就提供了内置的4个方法。
REST风格的应用最大限度地利用了协议自身已有的接口定义和内置操作,无需其它的规范和标准。

【JAX-RS】:Java API for RESTful Web Services。用来创建Restful WebService的Java API。

实验内容:
本实验分为两部分:(1)从POJO创建Restful WebService (2)用ADF调用Restful WebService
从前面的WebService实验,我们已经知道了POJO+元注释=WebService,把POJO变成Restful WebService也不例外。
只不过Restful中增加了一些特别的元注释而已。

重要步骤说明:

1. 创建Custom应用和项目。
教程本身提供了一个Project,为了彻底弄清创建Restful WebService的流程,我从头新建了应用。


2. 创建Emp.java和Service.java类,把内容复制过来。
Service.java会提示有错,选择“Create Project for JAX-RS Web Service”。

package restful;

import java.util.*;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/restlab")
public class Service {

    // Singleton Collection
    static ArrayList loe = new ArrayList();

    public Service() {
        super();
    }

    //Create
    public void addEmp(@QueryParam("id")
        int id, @QueryParam("exp")
        int exp, @QueryParam("name")
        String name, @QueryParam("sal")
        int sal) {
        Emp e = newEmp(exp, name, sal, id);
        loe.add(e);
    }

    //Read
    @GET
    @Produces("application/xml")
    public ArrayList getEmps() {
        return loe;
    }

    //Update
    public void upadteEmp(int delId, int id, int exp, String name, int sal) {
        deleteEmp(delId);
        addEmp(id, exp, name, sal);
    }

    //Delete
    @DELETE
    public void deleteEmp(@QueryParam("id")
        int id) {
        loe.remove(getObj(id));
    }

    //Helper Methods
    @PUT
    @Path("defaultEmp")
    public Response addEmp() {
        loe.add(new Emp("Adderley", 1, 5, 1000));
        loe.add(new Emp("Coltrane", 2, 6, 2000));
        loe.add(new Emp("Davis", 3, 7, 3000));
        return Response.ok().build();
    }

    Emp newEmp(int exp, String name, int sal, int id) {
        return new Emp(name, id, exp, sal);
    }

    public Emp getObj(int id) {
        Iterator i = loe.iterator();
        while (i.hasNext()) {
            Emp emp = (Emp)i.next();
            if ((emp.getId()) == id) {
                System.out.println(emp.getName());
                return emp;
            }
        }
        return null;
    }
}

完成后,会发现Service.java的图标变了,并且增加一些目录和文件。

JAX-RS的jar包也自动加进来了。

3. 测试WebService。

测试GET方法

测试PUT方法

测试DELETE方法

注意,以上的方法分别对应Service.java中的对应方法。

4. 创建ADF Web 应用,调用Restful WebService。
Restful WebService开发部署完毕,该如何调用呢?
这里使用ADF中URL Service Data Control。
GET URL Service Data Control:

GET URL Service Data Control返回值:

DELETE URL Service Data Control:

页面最终运行效果。


5. 在页面上,点击Delete按钮,记录没有被删除问题。
经检查发现是DataControls.dcx中行 Source="Restful/jersey/restlab?id=##id##. "
有错,改成Source="Restful/jersey/restlab?id=##id##"就好了。

6. 进一步思考,创建PUT URL Service Data Control,这样在页面上,所有功能就都有了。
这个任务留给聪明的你吧。

Project 下载:Restful.7z

2011年10月9日星期日

JDev_027:使用JDeveloper开发WebService之五:创建Web Service Data Control for ADF Client

开发环境:JDeveloper 11.1.1.5.0。
完成《Developing an ADF Client Using a Web Service Data Control 》。

Web应用如何调用WebService呢?
这里给出一个最简单的解决方案:创建Web Service Data Control for ADF Client。
关于ADF,请参考博客中其它文章,这里不做说明。
基本原理如下:
通过WSDL创建Web Service Data Control,在页面上拖放Data Control,让UI组件和WebService形成绑定关系。

重要步骤说明:
1. 创建Web Service Data Control。
首先要把已经发布的WebService运行起来,这里还是使用MyCompany WebService。


选择要调用的operation。

完成后,会生成Data Control。

2. 创建页面,拖放Data Control,生成绑定关系。

以下步骤省略。

Project 下载:WebServices (6).7z

JDev_026:使用JDeveloper开发WebService之四:创建Web Service Proxy

开发环境:JDeveloper 11.1.1.5.0。
完成《Creating a Web Service Proxy 》。

所谓“Web Service Proxy”,就是一个Java Client for WebService。
“Web Service Proxy”是通过WSDL2Java的过程生成的,它包括很多.java文件。
其中最重要的是一个*Client.java文件。

重要步骤说明:
1. 创建"Web Service Client and Proxy"。


这里我们使用之前发布的WebService:MyCompany。需要事先运行MyCompany Web Service。
WSDL地址指向该WebService的WSDL地址。

完成后,会生成很多文件:

选中*Client.java,添加测试代码



2. 测试WebService Proxy,右键*Client.java,运行即可。

Project 下载:WebServices (5).7z

JDev_025:使用JDeveloper开发WebService之三:元注释驱动EJB

开发环境:JDeveloper 11.1.1.5.0。
完成《Building an Annotation Driven EJB Web Service》。

EJB加上元注释,也可以而创建成一个WebService。
基本步骤与把POJO加上元注释创建成一个WebService的过程类似。


重要步骤说明:
1. 创建一个Stateless Session Bean。


这里我们不选择生成Local或Remote Interface,因为我们只把该EJB作为WebService访问。

添加方法。

添加元注释


2. 测试WebService。


Project 下载:WebServices (4).7z

JDev_024:使用JDeveloper开发WebService之二:WSDL驱动

开发环境:JDeveloper 11.1.1.5.0。
完成《Building a Web Service from an Existing WSDL》。

WSDL是用来描述WebService的,其中并没有说明如何实现该WebService。
当我们拿到一个WSDL文件时,通常面临两种情况:
(1)WebService已经实现了,我们需要根据WSDL来调用该WebService。
(2)WebService还没有实现,我们需要根据WSDL来实现该WebService。
本实验的情况是第(2)种。

重点步骤说明:
1. 选择创建“Java Web Service from WSDL"。


这里我们选择Java实现方式,即POJO。当然,你也可以选择EJB实现方式。

点击完成后,生成了很多类,不过最重要的是*Impl.java,因为这个类是WebService对应的Java实现类。

双击打开*Impl.java,添加自己的实现代码。
可以看到,元注释已经自动加入到这个POJO类中了。


2. 测试WebService。
步骤和上一个实验一样,从略。

Project 下载:WebServices (3).7z

JDev_023:使用JDeveloper开发WebService之一:元注释驱动POJO(2)

开发环境:JDeveloper 11.1.1.5.0。
完成《Building a Declaratively-Driven POJO Web Service》。

WebService Annotation虽然使得创建和发布WebService变得非常简单,但由于元注释元素很多,学习起来还是比较费时的。
有没有一些辅助手段,可以帮助我们生成这些元注释,而不必人工输入呢?
JDeveloper考虑到了这一点——它提供了一个Wizard帮我们生成元注释。
嘿嘿,真是我们开发人员的福气啊。

重点步骤说明:
1. 创建好POJO类以后,右键点击该类,选择“Create Web Service”


可以修改服务名和端口名

选择 SOAP1.2Binding

选择要发布WebService的operation,这里只有一个,因此默认选中。

点击Finish,生成的元注释如下:


2. 测试WebService
步骤跟上一个实验一样,这里省略。

3. 导出WSDL,保存到本地

然后可以选择File-> Save As

Project 下载:WebServices (2).7z

JDev_022:使用JDeveloper开发WebService之一:元注释驱动POJO(1)

开发环境:JDeveloper 11.1.1.5.0。
完成《Building a POJO Annotation-Driven Service》。

WebService Annotation是JavaEE 5的一个特性,它使得创建和发布WebService变得非常简单。
一个普通的POJO的Java类,加上元注释,就变成了一个WebService。
把元注释直接写在Java代码中,这样就不用在发布描述的XML文件中定义了。
每个.java文件,既是一个普通的Java类,又是一个WebService,一举两得。
在开发人员一端,无需任何配置;在服务器一端,也无需任何配置。
开发人员被从繁琐的配置文件中解放出来,可以专心致志地编写逻辑部分。
之所以不需要开发人员做任何配置工作,是因为:
在发布时,JavaEE将对编译后Java类进行“内省”(introspects),动态创建出WebService所需的配置。

重点步骤说明:
1. 创建好POJO类以后,在类名上面增加@WebService 注释,表明这个类同时是一个WebService。
点击“黄色灯泡”,选择“Configure Project for WebServices”,会帮我们创建web.xml等必要文件。



JAX-WS jar包也帮我们import进来了。


2. 添加新的方法,在方法名上面增加@WebMethod 注释,表明这是一个WebService的operation。
根据输入的部门ID,返回该部门对象。

修改ServiceName。

测试WebService。点击后,会自动启动内嵌的WLS,然后自动发布WebService,并启动HTTP Analyzer。

输入条件,得到响应。在HTTP Analyzer中可以看到请求和响应SOAP消息。
注意,该Java方法本身返回的是部门对象。
而响应的SOAP消息是把该部门对象中所有属性,包括集合属性:员工,都非常“合理地展开”了。

可以查看WSDL内容。


Project 下载:WebServices (1).7z