文's profile分享JAVA快乐BlogLists Tools Help

Blog


    12/26/2006

    配置MyEclipse的WebLogic服务器(转)

    配置MyEclipse的WebLogic服务器
    MyEclipse默认的应用服务器为JBoss3,这里我们使用WebLogic8.1。启动Eclipse,选择“窗口\首选项”菜单,打开首选项对话框。展开MyEclipse下的Application Servers结点,点击JBoss 3,选中右面的Disable单选按钮,停用JBoss 3。然后点击WebLogic 8,选中右边的Enable单选按钮,启用WebLogic服务器。同时下面的配置如下:
    (1)BEA home directory:D:\BEA。假定WebLogic安装在D:\BEA文件夹中。
    (2)WebLogic installation directory:D:\BEA\weblogic81。
    (3)Admin username:user。
    (4)Admin password:12345678。
    (5)Execution domain root:D:\BEA\user_projects\dev。
    (6)Execution domain name:dev。
    (7)Execution server name:admin。
    (8)Hostname:PortNumber:localhost:7001。
    (9)Security policy file:D:\BEA\weblogic81\server\lib\weblogic.policy。
    (10)JAAS login configuration file:省略。
    接着展开WebLogic 8结点,点击JDK,在右边的WLS JDK name处选择WebLogic 8的默认JDK。这里组合框中缺省为j2re1.4.2_03,即之前单独安装的jre。单击Add按钮,弹出WebLogic > Add JVM对话框,在JRE名称处随便输入一个名字,如jre1.4.1_02。然后在JRE主目录处选择WebLogic安装文件夹中的JDK文件夹,如D:\BEA\jdk141_02,程序会自动填充Javadoc URL文本框和JRE系统库列表框。单击确定按钮关闭对话框。这时候就可以在WLS JDK name组合框中选择jre1.4.1_02了。之后还要在下面的Optional Java VM arguments,如-ms64m -mx64m -Djava.library.path="D:/BEA/weblogic81/server/bin" -Dweblogic.management.discover=false -Dweblogic.ProductionModeEnabled=false
    最后点击Paths,在右边的Prepend to classpath列表框中,通过Add JAR/ZIP按钮,加入D:\BEA\weblogic81\server\lib\weblogic.jar、D:\BEA\weblogic81\server\lib\webservices.jar。如果用到数据库,还需把数据库的驱动类库加进来,这里我们用WebLogic自带的SQL Server数据库驱动库D:\BEA\weblogic81\server\lib\mssqlserver4v65.jar。
    至此,MyEclipse中WebLogic8的配置工作就算完成了。下面可以看看在Eclipse中能否启动WebLogic了?自从安装了MyEclipse之后,Eclipse工具栏中就会有一个Run/Stop Servers下拉按钮。点击该按钮的下拉部分,选择“WebLogic 8\Start”菜单,即开始启动WebLogic了。通过查看下面的控制台消息,就可以知道启动是否成功,或有什么异常发生。停止WebLogic可选择“WebLogic\Stop”菜单。
    12/20/2006

    生病了

    住了一个星期的医院,累,在医院就想着快点能上班,可是想想碰电脑时间久了又会厌.
    好些东西都是矛盾的.具有两面性质.
    这几天生病多亏了同学和老师的关心跟照顾,不然麻烦就大.同时也很开心,女朋友从苏州赶来看我了.
    相距的日子时间总是短暂的,很快我就送人家回去了.呵呵,也好,小别胜新欢,保持不变的心态,短暂的分离又有什么呢.
    本来明天就想去公司了,领导说了,让我星期一去,那我就好好休息.
    医院是吃人的,钱赚了都给医院了:(
     
    10/13/2006

    让女孩看了流泪,男孩看了沉默的故事

          有那么一对情侣.女孩很漂亮,非常善解人意,偶尔时不时出些坏点子耍耍男孩.男孩很聪明,也很懂事,最主要的一点.幽默感很强.总能在2个人相处中找到可以逗女孩发笑的方式.女孩很喜欢男孩这种乐天派的心情.
      他们一直相处不错,女孩对男孩的感觉,淡淡的,说男孩象自己的亲人.
      男孩对女孩爱甚深,非常非常在乎她.所以每当吵架的时候,男孩都会说是自己不好,自己的错.即使有时候真的不怪他的时候,他也这么说.他不想让女孩生气.
      就这样过了5年,男孩仍然非常爱女孩,象当初一样.
      有一个周末,女孩出门办事,男孩本来打算去找女孩,但是一听说她有事,就打消了这个念头.他在家里呆了一天,他没有联系女孩,他觉得女孩一直在忙,自己不好去打扰他.
      谁知女孩在忙的时候,还想着男孩,可是一天没有接到男孩的消息,她很生气.晚上回家后,发了条信息给男孩,话说得很重.甚至提到了分手.当时是晚上12点.
      男孩心急如焚,打女孩手机,连续打了3次,都给挂断了.打家里电话没人接,猜想是女孩把电话线拔了.男孩抓起衣服就出门了,他要去女孩家.当时是12点25.
      女孩在12点40的时候又接到了男孩的电话,从手机打来的,她又给挂断了.
      一夜无话.男孩没有再给女孩打电话.
      第2天,女孩接到男孩母亲的电话,电话那边声泪俱下.男孩昨晚出了车祸.警方说是车速过快导致刹车不急,撞到了一辆坏在半路的大货车.救护车到的时候,人已经不行了.
      女孩心痛到哭不出来,可是再后悔也没有用了.她只能从点滴的回忆中来怀念男孩带给她的欢乐和幸福.
      女孩强忍悲痛来到了事故车停车场,她想看看男孩呆过的最后的地方.车已经撞得完全不成样子.方向盘上,仪表盘上,还沾有男孩的血迹.
      男孩的母亲把男孩当时身上的遗物给了女孩,钱包,手表,还有那部沾满了男孩鲜血的手机.女孩翻开钱包,里面有她的照片,血渍浸透了大半张.
      当女孩拿起男孩的手表的时候,赫然发现,手表的指针停在12点35分附近.
      女孩瞬间明白了,男孩在出事后还用最后一丝力气给她打电话,而她自己却因为还在堵气没有接.男孩再也没有力气去拨第2遍电话了,他带着对女孩的无限眷恋和内疚走了.
      女孩永远不知道,男孩想和她说的最后一句话是什么.女孩也明白,不会再有人会比这个男孩,更爱她
    10/12/2006

    修改weblogic console登陆的用户名和密码

        在XP系统上安装了weblogic server 8.1,安装成功后,启动服务器,系统显示服务器正常启动。在IE6.1中输入http://localhost:7001/console后,出现要求登陆的界面。那如何修改安装时设定的用户名和密码呢?

    注:console的密码一般都是在安装的时候指定的。

    第一步:在console端使用原来的用户名和密码登陆,再进入Your Appliation's Security Setting的Realms,再进入myrealm,进入user Managerment,进入manager users within this Security Realm;[该操作界面 可以修改“删除”老的用户,“新增”管理用户]

    第二步:在manager users within this Security Realm操作界面上,可以新建一个用户,注意必须将该用户设定到管理员组内,否则该用户无法在console上登陆; 还可以修改原登陆者的密码[weblogic的密码是8位数字以上]

    第三步:关闭wls服务进程;

    第四步:备份你的config.xml和boot.properties文件,为了避免修改操作失误;

    如果没办法回复到修改密码前的那种状态,那只能建议你重配Domain了.

    第五步:修改boot.properties文件是可以的,
            username=weblogic
            password=123456789
          记着用户名和密码都不加引号,否则启不来。启动完后用户名和密码自动就变成密文了。
          或者你把boot.properties的用户名和密码清空,启动时手工输入用户名和 密码也是可以的。

    注:其实你把boot.properties删掉也没关系。只要你知道一套正确的管理员帐号密码就行,只不过每次启动server要输入。

    10/1/2006

    New features added to Servlet 2.5


    Servlets updated with annotations, web.xml conveniences, and more
     
     
    On September 26, 2005, Sun Microsystems and the Java Specification Request 154 Expert Group issued a maintenance
    release of the Servlet API. Under normal circumstances, a JSR maintenance releases includes just a handful of
    nominally interesting specification clarifications. However, in this case, the release added several new features
    and changes, and made enough of an impact on servlets to justify a bump in the version number to Servlet 2.5.
    In this article, I explain what's new in this Servlet 2.5 release. I describe each change, provide background on why
    the change was necessary, and show how to use the change in your own servlet-based programs.
    This is actually my sixth article documenting Servlet API updates for JavaWorld. I intend these articles to serve
    two purposes: in the short term, to introduce you to the new features and, in the long term, to act as a historical
    compendium of changes, so when you find yourself coding against a past Servlet API version, you can determine
    exactly what features and behavior you can and can't depend on. Check Resources for my previous servlet articles.
    Please remember: When experimenting with these new features and capabilities, not all servlet containers or Java
    Enterprise Edition (JEE) application servers jump immediately to the latest Servlet API release. At the time of this
    writing, the Jetty 6 server and Sun's GlassFish server are the two best-known servlet containers that include 2.5
    support. Apache Tomcat 5.5 and JBoss 4.0 still support Servlet 2.4.
    Among the changes introduced in Servlet 2.5:

    A new dependency on J2SE 5.0
    Support for annotations
    Several web.xml conveniences
    A handful of removed restrictions
    Some edge case clarifications
    Dependency on J2SE 5.0
    To begin with, the Servlet 2.5 specification now lists J2SE 5.0 (JDK 1.5) as its minimum platform requirement. While
    this limits Servlet 2.5 to those platforms with J2SE 5.0 implementations, this change means that all the new
    language features from J2SE 5.0 (generics, autoboxing, an improved for loop, a new enum type, static importing,
    varargs, and metadata annotations) are guaranteed available to Servlet 2.5 programmers.
    Traditionally, servlet and JEE releases have moved forward at the measured pace of one JDK level at a time, but this
    time, the servlet release skipped version 1.4. The expert groups considered the double jump to be justified because
    J2SE 5.0 offered one compelling feature that the servlet and JEE specifications wanted to use themselves:
    annotations.
    Annotations
    Annotations are a new language feature provided as part of JSR 175 (A Metadata Facility for the Java Programming
    Language). Annotations provide a mechanism for decorating Java code constructs (classes, methods, fields, etc.) with
    metadata information. Annotations aren't executed like code, but, rather, mark code in such a way that code
    processors may alter their behavior based on the metadata information.
    When you think about it, we've been annotating classes and methods all along with different tricks like the
    Serializable marker interface (to alter serialization) or the @deprecated Javadoc comment (to alter compilation).
    The new metadata facility simply provides a standard mechanism for doing annotations and a vehicle for libraries to
    create custom annotation types.
    Here's a simple Web service annotation example:

    import javax.jws.WebService;
    import javax.jws.WebMethod;
    @WebService
    public class HelloWorldService {
      @WebMethod
      public String helloWorld() {
        return "Hello World!";
      }
    }

    The @WebService and @WebMethod annotation types, specified in JSR 181 (Web Services Metadata for the Java Platform)
    and imported just like classes, mark this class as a Web service and mark its helloWorld() method as a Web service
    method. By themselves, the annotations don't do anything but sit there, kind of like Post-It notes; however, a
    container, upon loading this class and seeing those annotations in the bytecode, can wire up the class for Web
    services.
    Annotations may accept name/value parameters. The parameter information is kept with the annotation and can be used
    to alter the behavior requested by the annotation. For example, here's a more advanced annotation example:

    @WebService(
      name = "PingService",
      targetNamespace="http://acme.com/ping"
    )
    @SOAPBinding(
      style=SOAPBinding.Style.RPC,
      use=SOAPBinding.Use.LITERAL
    )
    public class Ping {
      @WebMethod(operationName = "Foo")
      public void foo() { }
    }

    Upon loading this class, a proper container will respect the annotations and their parameters, and wire up the class
    as a PingService with a Foo operation using the remote-procedure-call/literal encoding style. In a sense,
    annotations define the contract a class wishes to have with its container.
    The Java language itself (through JSR 175) specifies only a tiny number of annotation types. The interesting
    annotation types come from other JSRs:

    JSR 250: Common Annotations for the Java Platform
    JSR 220: Enterprise JavaBeans 3.0
    JSR 224: Java API for XML-Based Web Services (JAX-WS) 2.0
    JSR 181: Web Services Metadata for the Java Platform
    See Resources for more details on metadata and annotations.
    Annotations in Servlet 2.5
    Coming back to Servlet 2.5, the new specification describes how several annotations work in a servlet environment.
    Simple servlet containers can ignore these rules, while servlets in a JEE container must abide by them.
    Some annotations provide an alternative to XML entries that would otherwise go in the web.xml deployment descriptor.
    Other annotations act as requests for the container to perform tasks that otherwise the servlet would have to
    perform itself. Some annotations do both.
    The exact list of annotations isn't completely finalized, because the Servlet specification itself doesn't define
    the annotations; it only helps interpret how they affect a servlet environment. Here's a short summary of the
    annotations you can expect in JEE 5 along with their intended use:

    @Resource and @Resources: @Resource is placed on a class or variable to request a "resource injection" by the
    servlet container. When the container sees this annotation, it will prepopulate the annotated variable with an
    appropriate value before the servlet gets placed into service. By using this annotation, you avoid the need to make
    a JNDI (Java Naming and Directory Interface) lookup call and declare the resource manually in the web.xml deployment
    descriptor file. The server takes care of both tasks through introspecting the servlet. The name and type of the
    variable are determined automatically by reflection, although you can override that with annotation parameters. An
    injected resource may be a datasource, Java Message Service destination, or environment entry variable. Here's a
    basic example:
    @Resource javax.sql.DataSource catalog;
    public getData() {
      Connection con = catalog.getConnection();
    }

    Now, before putting a servlet with this code into service, the container will locate the JNDI variable named catalog
    of type DataSource and manually assign that reference to the catalog variable.
    For efficiency, only certain classes support resource injection: servlets, servlet filters, servlet event listeners,
    JavaServer Pages tag handlers and JSP library event listeners, JavaServer Faces scoped managed beans, and a few
    other class types unrelated to servlets.
    The @Resources annotation is similar to @Resource, but used to hold an array of @Resource annotations. Both
    annotations are from JSR 250, the Common Annotations for the Java Platform.

    @PostConstruct and @PreDestroy: Attached to methods to make them act as lifecycle methods. The @PostConstruct method
    is called after the resource injection as a chance to initialize the injected resources. The @PreDestroy method is
    called when the servlet is taken out of service to give it a chance to release injected resources. The callback
    methods must be instance methods that return void and do not throw any checked exceptions. In a servlet, these
    annotations essentially let arbitrary methods act as secondary init() and destroy() methods. These properties also
    come from JSR 250.
    @EJB: Similar to @Resource, except designed for injecting Enterprise JavaBeans references. It has somewhat different
    parameters than @Resource in that @EJB parameters are specifically designed to locate EJB references. This
    annotation comes from the EJB 3.0 specification.
    @WebServiceRef: Similar to @Resource and @EJB, except designed for injecting Web service references. From the JAX-WS
    2.0 Specification.
    @PersistenceContext, @PersistenceContexts, @PersistenceUnit, and @PersistenceUnits: Annotations from the EJB 3.0
    Specification to support Java object persistence.
    @DeclareRoles: Defines the security roles used within the application. When defined on a servlet class, this
    annotation offers an alternative to <security-role> entries in the web.xml file. From JSR 250.
    @RunAs: Used to declare the role under which a class should run. When defined on a servlet class, it's an
    alternative to <run-as> entries in the web.xml file. From JSR 250.
    Annotation performance
    Whether or not you use annotations—and especially if you don't—it's important to understand the performance impact
    they can have on a server at startup. In order for the server to discover annotations on classes, it must load the
    classes, which means that at startup, a server will look through all the classes in WEB-INF/classes and WEB-INF/lib,
    looking for annotations. (Per the specification, servers don't have to look outside these two places.) You can avoid
    this search when you know you don't have any annotations by specifying a metadata-complete attribute on the <web-
    app> root like this:

    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
             version="2.5" metadata-complete="true">
    </web-app>

    When you're not using annotations, this reenables lazy class loading.

    web.xml conveniences
    Servlet 2.5 introduces several small changes to the web.xml deployment descriptor file format to make its use more
    convenient.
    Servlet name wildcarding
    First, when writing a <filter-mapping>, you can now use an asterisk in a <servlet-name> entry to represent all
    servlets (and thus all JSP pages as well). Previously, you could only bind one servlet at a time to a filter, like
    this:

    <filter-mapping>
      <filter-name>Image Filter</filter-name>
      <servlet-name>ImageServlet</servlet-name>
    </filter-mapping>

    Now you can bind all servlets at once:

    <filter-mapping>
      <filter-name>Image Filter</filter-name>
      <servlet-name>*</servlet-name>  <!-- New -->
    </filter-mapping>

    This proves most useful when creating general rules like, "Execute a filter on all forwards to a servlet," which is
    written like this:

    <filter-mapping>
      <filter-name>Dispatch Filter</filter-name>
      <servlet-name>*</servlet-name>
      <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

    Multiple patterns in mappings
    Second, when writing a <servlet-mapping> or <filter-mapping>, you can now provide multiple match criteria in the
    same entry. A <servlet-mapping> previously supported just one <url-pattern> element. Now it supports more than one.
    For example:

    <servlet-mapping>
      <servlet-name>color</servlet-name>
      <url-pattern>/color/*</url-pattern>
      <url-pattern>/colour/*</url-pattern>
    </servlet-mapping>

    Likewise, a <filter-mapping> previously allowed just one <url-pattern> or one <servlet-name>. Now it supports any
    number of each:

    <filter-mapping>
      <filter-name>Multipe Mappings Filter</filter-name>
      <url-pattern>/foo/*</url-pattern>
      <servlet-name>Servlet1</servlet-name>
      <servlet-name>Servlet2</servlet-name>
      <url-pattern>/bar/*</url-pattern>
    </filter-mapping>

    Both these changes are syntactic sugar, but so be it. There's no reason we should program low carb.
    HTTP method names
    Lastly, you can now place any legal HTTP/1.1 method name into an <http-method> element. As you may recall, the
    <http-method> element specifies the methods on which a <security-constraint> entry should apply. It's historically
    been limited to the seven standard HTTP/1.1 methods: GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE. However,
    HTTP/1.1 allows for extension methods, and WebDAV is a popular technology using extensions. With Servlet 2.5, you
    can now apply security constraints on any conceivable HTTP method name, standard or extension, including WebDAV
    methods like LOCK, UNLOCK, COPY, and MOVE.
    Just don't look for doLock() or doCopy() methods if you're writing a WebDAV servlet. You'll have to write your own
    service() method and peek at the request.getMethod() for dispatching. You just won't have to manage your own
    security, thanks to this change.
    Restriction removal
    Servlet 2.5 eased a few restrictions around error handling and session tracking. With error handling, Servlet 2.5
    removed a rule dictating that error-handling pages configured with <error-page> could not call setStatus() to alter
    the error code that triggered them. The rule followed the argument that the job of an error page is to report each
    error but not alter it. However, practical use has made clear that sometimes an error-handling page may be able to
    do something more graceful than show an error, perhaps choosing instead to show an online help chat window to help
    the user resolve the problem. The specification no longer prevents an error-page handler from producing a nonerror
    response.
    Regarding session tracking, Servlet 2.5 eased a rule dictating that a servlet called by RequestDispatcher include()
    couldn't set response headers. This rule's purpose was to keep included servlets constrained within their own space
    on the page, unable to affect the page outside that area. The rule has eased now to allow request.getSession() calls
    within the included servlet, which might implicitly create a session-tracking cookie header. Logic dictates an
    included resource should be constrained, but logic also dictates those constraints shouldn't eliminate the ability
    to initiate a session. This change proves especially important for the Portlet Specification. Note that if the
    response was already committed, the getSession() call will throw an IllegalStateException. Previously, it would have
    been a no-op.

    Clarifications
    Lastly, the new specification clarifies several edge cases to make servlets more portable and guaranteed to work as
    desired.
    Response closure
    The first clarification is trivial and esoteric, but interesting as an example of the unintended side effects you
    sometimes see in a specification. The Servlet 2.4 specification dictates that the response should be committed (that
    is, have the response started with the status code and headers sent to the client) in several situations including
    when "The amount of content specified in the setContentLength method of the response and has been written to the
    response." This appears all well and good until you write code like this to do a redirect:

    response.setHeader("Host", "localhost");
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Content-Length", "0");
    response.setHeader("Location", "http://www.apache.org");

    The servlet technically must ignore the Location header because the response must be committed immediately as the
    zero byte content length is satisfied. The response is over before it began! Servlet containers often refuse to
    implement this behavior, and the Servlet 2.5 release adds "has been greater than zero" to the rule.
    Encoding edge cases
    The Servlet 2.4 specification says you must call request.setCharacterEncoding() before calling request.getReader().
    However, it does not say what happens if you ignore this advice and make the setter call after the retrieval. For
    portability, it's now clarified to be a no-op.
    Cross-context sessions
    Lastly, the rules around cross-context session management have been clarified. This comes into play when servlets
    dispatch requests from one context to another. Within the target call, what session should be in scope, if any? The
    issue came up most prominently with portlets, where a main page in one context may do several include calls to
    portlets in another context. Servlet 2.5 now specifies that resources within a context see the session for that
    context, regardless of where the request may have started. This means the portlets can track their own state
    separate from the main page state, and this rule will apply across servlet containers.
    Still on the wish list
    Because of the maintenance review nature of the Servlet 2.5 release, several larger ideas had to be postponed until
    the next review phase. Among the ideas postponed:

    New Input/Output (NIO) support: It's possible NIO Channels would be a more efficient way for servlets to communicate
    with clients.
    Filter wrap-under or wrap-over semantics: People sometimes use filters to wrap the request and/or response objects
    to alter method behavior or expose new methods. When this wrapping is combined with a server's need to wrap the
    request and response as part of a request dispatch, how do the wraps fit together?
    Servlets as welcome files: Should an index.do be able to act as a welcome file? Historically, the answer has been
    yes. But the specification doesn't clarify how to allow that functionality, especially if no index.do is on the
    filesystem, but a *.do mapping is, which would always exist virtually and shadow other welcome files.
    Welcome file dispatch rules: The details on how to dispatch to welcome files have not been exhaustively specified
    and leave open cracks for incompatibility.
    Selecting a default page after login: If users visit a servlet's form-based login page from their bookmarks, where
    should they be sent after a successful login? It's unspecified today.
    Programmatically log in a user: Right after a user registers with a site, there's no way to inform the servlet
    environment about the user's credentials without the user performing a traditional login.
    Update: March 6, 2006
    After this article was first published, Sun issued a Servlets 2.5 MR2 (second manufacturing release) that includes a
    few changes from the first manufacturing release:

    The attribute full on the <web-app> root was renamed to the more descriptive metadata-complete. This change has been
    incorporated into the above text.
    A new method getContextPath() was added to ServletContext. Formerly context path information was only available in
    the request object, following the logic that the same context object might be bound to multiple paths so you'd only
    know the path at request time. However, no known servers have utilized the multiple path binding option, and a
    context being able to report its path is often convenient, so the method got the green light. Should it ever happen
    that a context be bound to multiple paths, it will return its "preferred" path.
    Conclusion
    If you look at the Servlet 2.5 changes apart from annotations, the new release does a nice job of giving web.xml a
    little syntactic sugar, of removing a few restrictions that were getting in the way, and of clarifying edge case
    behavior to enable more powerful and portable component-based Webpages.
    The effect of annotations in Servlet 2.5 looks more dramatic. It's important to remember that servlets themselves
    don't define any new annotation types, and simple servlet containers don't even have to support annotations. Yet
    servlets authored for a JEE 5 environment will see their code change a lot from the annotation types introduced by
    common annotations and the EJB 3.0 and JAX-WS 2.0 specifications, and these will have a big impact on how servlets
    manage external resources, object persistence, and EJB components.
     
     
     
     

     
    9/24/2006

    JBoss部署Web 程序

    昨晚搞了个通宵,研究了下子JBoss,因为想学EJB。
    感觉跟Tomcat差不多。
    我用的是jboss-4.0.4RC1,安装后有六个文件夹。分别是bin,client,server,lib,docs和Uninstaller
    部署的时候把Web工程打包成.war文件,放在server\default\deploy文件夹下(default可以在安装JBOSS的时候更改名字),启动服务器(在bin文件夹下有run.bat批处理文件,相应的关闭是shutdown.bat,里面还有deployer.bat,twiddle.bat文件没试用)。
    在浏览器里输入http://localhost:8080/工程名,OK.
    server\default\log有日志文件,这是查错的法宝。
    9/21/2006

    一个多月学到的东西

    Debug,F7进,F8逐行
    拿本记事本记点工作日志。
    认识了几个朋友。
    增强了对SQL的理解,学会了用Oracle,Oracle Object Browser for Windows,了解了JBuilder 2005,
    学会用 PL/SQL.见识了PowerDesigner.试用MyEclipse5.0。
    用了Weblogic 8.1,知道还有 Workshop的存在。
    理解了工作压力。
     
    时刻记得,自己还要照顾佳艺。
     
    要保持自信啊,虽然有困难,爬过了这座“山峰”就没事了。
     
    明天依然要挤拥挤的公交,地球依然要转,自己的人生很短暂。
     
    8/27/2006

    一位软件工程师的6年总结

    1、   分享第一条经验:“学历代表过去、能力代表现在、学习力代表未来。”
    2、   一定要确定自己的发展方向,并为此目的制定可行的计划。
    3、   软件开发团队中,技术不是万能的,但没有技术是万万不能的!
    4、   详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)
    5、   书籍是人类进步的阶梯,对软件开发人员尤其如此。
    6、   不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。
    7、   在一种语言上编程,但别为其束缚了思想。
    8、   养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。
    9、   理论与实践并重,内外双修
    10、心态有多开放,视野就有多开阔。
    11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品,千万不要因为没有钱赚而不做
    12、书到用时方恨少,不要将自己的知识面仅仅局限于技术方面。
    13、
            A:不要去做技术上的高手,除非你的目标如此。虽然本文是关于提高软件开发知识的建议,做技术的高手是我一向都不赞同的。你可以提高自己的专业知识,但能胜任工作即止。

    B:提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理,可以很容易地延伸、应用到生活的其它方面。

    C:在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。

    8/26/2006

    大项目中项目经理的作用(转)

    前言:本文作者结合自己的经历谈谈项目经理在企业信息化建设项目中的作用和项目操作,以供大家参考,希望对大家的工作有所实际帮助。作者有幸参加了广东省联通、广东省电信以及其他更大的一些集团的项目运作,文章是从作者自身的角度和经历总结的一些问题,不足之处请广大同行指点,借此抛砖引玉以期和广大同行共勉共同进步。
    序:大项目在本文的定义为企业信息建设中客户大名气高而且项目金额大,在我国,能签下大项目的单有一部分是靠草根阶层更专业化的服务和质量以及行业客户赢得的,但一般而言签下的这样的大项目对软件开发商而言都不可能是天平两端同样的法码,所以销售人员为了能签下这样的大单一般都不得不答应或是承诺一些超越公司目前实力和技术水平的需求,因为不这样根本就没有竞争的机会。这样的苦果程序员即使抱怨非常多,还是不得不照样加班加点去拼命实现。(想想国外的厂商做中国的市场真是爽,国内的客户无不乖乖地听他们的话)
      目前国内的软件公司靠产品批发赚大钱的非常少,象金蝶和用友上也都有靠签大项目来发展,所以大项目的成败及效率就直接影响着公司运营成本和利润以及大家的薪金收入。因为一开始签定的就是不平等条约,所以项目经理的人选更是直接决定了项目的成败和收益。这样的项目经理有两种,一是为自己镀金的,那是非常光荣和开心的事,因为费用及人手配置都非常充足,第二种是很有责任心而且想做成功的项目经理,会做得非常辛苦,累得半死。如何让项目早些验收让领导放心,让下属开心和放松是项目经理时时刻刻都关注的事。
      正文:结合自己的经验谈谈项目经理在主持项目实际运作时的二个要点三种避免和四个注意。希望对大家的实际工作会有所帮助!
      两个要点
      一、如何尽快地将项目验收回款,为公司和团队创造更多的利润,为下属带来更多的利益。
      二、板回双方不平等中的劣势
      这是项目中非常关键的一个心理预期,因为早期签的合同让开发商处于劣势,客户从你进场开始自然而然地在气势上压着你,如果你长期处于心理上的劣势,项目失败的风险就非常高,因为大公司中的人员都有一种出了事情后他们会将你原本认为是他们的责任的推得干干净净,如果你纠缠下去和他们的关系就搞僵了,项目的后期工作会非常难进行,公司高层考虑的就是更换项目经理,因为这时的客户真的是上帝,老板都不敢得罪的人你得罪的后果大家都知道会怎样。笔者当初和他们打交道时就花了一个月多的时间让整个团队在专业上体现出来是行家和经验娴熟,因为客户是大公司的,技术资源很丰富,他们懂的面很广,也有知道得深的,所以要抓住机会和他们多交流特别是非工作时间,首先你要认可他,然后让他感觉他专业,再然后你在合适的机会某些方面要自然而且不露痕迹地表现出你知道得更深更专业,当然当初没少花我银子。劣势板回后,后期他们才会注重你说话的份量,才可以指出哪些需求是不合理的,哪些是微软都没有办法做到的。
       
      三个避免
      一、避免事情太多杂乱无章
      大项目也意味着需求多,参与的人员也多,如何保证项目的进度,避免事情太多,需求点太多而导致最后项目失控,就是项目组加班加点做了大量的工作,最后却发现什么都没有做好,客户不认可,领导很焦虑,下属很失望,你很郁闷的局面。在项目进行过程中不可避免地会遇到很多提出的需求和修改意见,如何快速把握这些需求提出正确可行的解决方案是项目经理首先要考虑的事情。别忘了项目合同上都是有时间限制的,如何在时间段之内完成项目而且完成得好就是关键。一味地否认抵制客户的需求当然不行,全盘照收只会让项目越变越大,项目组的人每日每夜地加班。笔者的作法一般是记录成文字性的文档,然后根据实际情况提出哪些现在做,哪些暂时不做,哪些到二期或三期工作时再考虑,并请他们确认。这套方法笔者常用不衰,希望对各位项目经理在项目运营过程有实际的帮助。
      二、避免太多个性化的需求
      这是最头痛的事情,因为客户是大公司,会议没完没了,每个会议都要求得非常正规,而且客户看起来确实是很正规,相关的制度文档相关的人员以及部门级的经理都甚至高层的领导也会请到会议室来和你谈需求,每个经理都会有自己的部门的特点和需求,如何尊重他们的意见并保持自己的思路是非常重要的。笔者早期参加这样的会议时也一样很听客户的话,程序实现的过程中则是非常痛苦,经历过多次后,笔者建议各位项目经理要保证突出你们的专业知识和经验,不要被客户的职位所迷惑了,因为他们的经验很丰富,但在专业特别是软件方面你是专家,而且他们提出的是现实中各个部门的特点,并没有要求软件一定要实现。所以现场一定要记住,不要答应得太快,笔者后面就养成了一句口头禅,我们回去研究讨论后再确定。
      三、避免人浮于事的现象
      大公司都会有的现象,如何让你的项目组成员在项目进行过程中最大限度地减少这样的消耗是项目经理要关注的事。大公司踢皮球的现象大家都有所耳闻,所以做为项目经理的你能做就是如何做好事前的工作,避免出了问题后指责,到时你会发现没有人和这有关,都是你的错。所以少些抱怨,事前尽可能多做准备。笔者最常用的方法就是在需求说明书(实际工作中提出,非早期完整的需求说明书)中注明这是某某人提出的,以及我们的意见是什么,你别指望他会签字,一个需求点如果要等他确认签字你就等个两个星期吧。
    四个注意
    一、注意内部团结一致,互帮互助和高度的热情保证得项目快速往前推进。
        项目小组的团结一致,这是基石,不论是在需求讨论分析,还是开发过程和项目内部测试,大家都团结一结,不断提出自己的看法一起交流,在最短时间内将问题细化和明确下来,大大缩短了开发周期。保持项目小组成员高度的热情使得项目讯速得到突破,达到了预期的要求,这是项目经理真正最重要的工作。在项目运作过程中,别忘记项目小组不是孤军奋战,背后还有整个公司的资源别忘了使用。
      二、注意项目进度的严格控制
      这是老生长谈的问题,核心还是《人月神话》,在现有的人手配置和资源上如何控制项目的进度,这是所有项目经理也是公司领导最关注的事情。因为大项目的进度要控制出了偏差,后期很多预想不到的事情会让你焦头烂额的。所以必要的会议还是要开,总结和安排工作是每周都必须要进行的工作,笔者当初是将工作总结工作安排和需求讨论严格分开的,即使是参加的人员一样。因为需求讨论需求分析有时是无底洞,有些实现起来是有难度的,这时在会议上一定要注意控制方向鼓励大家踊跃发言的同时要保证主题方向。因为需求的扩散和实现的难度将直接影响到项目的进度,很多项目最后失控追根结底相当一部分原因是需求没有把握住。笔者一同事负责的一个百万级的项目,超过签定合同时间的半年了还没有完成,公司后期调动了所有可调用的技术人员进入项目组,搞得人人疲惫,当初最大的原因就是客户的需求不断扩散导致程序开发无休止地进行。
      三、注意搞好各方面的关系
      项目经理首先要搞好的是你和你的领导的关系,特别是老板的关系,你要体会你的老板的心情,他是希望做成功大项目然后开始扩张,他的心里比你更关注项目的进展,要是出问题他心里比你更焦虑,所以记得要让你的老板参与到项目中来,别因为他不懂技术不懂项目管理就把他晾在一边。笔者的做法是每周都会将工作写成简单的总结发给上级领导,然后抄送给BOSS,有什么计划要执行或调整时预先做好书面材料发送给领导们,这时要忌讳的就是越级上报,所以这样的计划我一般是只发送我的直属上级,在MAIL中写到等计划正式拟定后请他转呈老总,大的事情一般是他都会在比你更期望的时间代你向老总汇报了,因为只有和老总搞好关系,他才会信任你,而且还会源源不断地支持你,不然一些公司接到一个大项目要失败了,公司搞不好就负债了,所以你要明白BOSS可能是将公司前途放在你身上。接下来就是要搞好下属的关系,他们是实现完成工作的核心和中流抵柱,平时要舍得花些银子请他们吃吃饭组织一些体育活动,程序员都是典型的亚健康状态,看看程序员那象怀胎三个月的肚子就知道了。再接着就是要搞好客户的关系了,除了言语上尊重他们外,必要的银子还是要花的,而且要花得有特色,因为他们聚餐也不少啊。所以大家明白我为何要将搞好和老总的关系放在第一位了吧,不然这些白花花的银子,老总不签字,项目再失败了,你赔了血本都不够啊,呵!
      四、注意项目验收的各个环节
      这是大家都关心特别是老总最关心的问题了,有时你别看他表面上非常平静,一点都没有开心的样子,我的老总那天在去洗手间的路上就哼起了小曲,这是好几年都没有的事情。但是要达成这样的任务并不是象小项目那样双方有意向后谈一天就可以签字,大公司都有自己一套套的验收标准,如果按照他们那样的标准,你卖硬件都难,更不用说软件了,而且谁在这上面签了字以后出了问题谁就要负责,而且软件永远都没有100%没有问题的,你看微软还不是不断升级和发补丁包。如何采用让双方都能接受的方式签定验收合同就要求你平时就要做好准备,笔者一般是每个月都会有一个功能模块实现的清单请他们确认,要他们签字是不可能,笔者的做法是请他们指出哪些没有完成的或有意见的,这样日积月累下来,对方认可了你的工作,后面他个人这一关是可以通过了,后面一定是他的上级以及副总层层把关,记住这时谈的一定要是实现完成了哪些功能,对新需求的千万不能答应就改,可以放到后期,并在验收合同中注明哪些是新需求还没有完成的,层层把关让折磨你的性情考验你的耐性,两周之内要能签下字就算是顺利了。还有一点有过大项目经验的仁兄有没有注意到,项目验收签字的都是客户的最高层和最低层两三个人的名字一起签在上面,中间管理层做了许多幕后工作,所以在验收的过程中不要忘记向客户的每个上级多表扬一下项目中参与的他下属人员的业绩,当他们都是功臣时在最后一关卡住的机会会少很多。因为最后一关没有通过,所有的一切努力都是白搭!希望此篇文章对广大同行能有实际的帮助,祝各位同仁都能在项目验收的庆功宴上多喝两杯。
    作者:郑德辉,2000年毕业后一直从事MIS软件开发,近几年一直从事人力资源软件的开发,参与负责主持了大小三十多个项目,希望和广大同行共同交流心得经验,联系方式dhuiz@sohu.com
    8/23/2006

    好笑

    今天下班在餐厅吃饭,厨房的伙计跟两个人在摆弄v500,靠,不得了。
    哎,“我这内存比你的多,能听完整的歌”,一个V3的说。
    科技发达了,计算机知识普及了,左一个内存,右一个内存,昏啊。吃不消。

    我怀着钻研精神,终于被我知道,同事的想法是错的

    1.Tools->Configure->JDKs,要把JDK5.0加進去。2005他自帶的JDK還是1.4版。

    2.Project->Project Properties->Paths-JDKs
    選剛剛加入的JDK5.0

    3.Project->Project Properties->Build-Java。
    Language features設Java 2 SDK, v5.0 (generics enabled)

    4.Project->Project Properties->Build-Java。
    Target VM設Java 2 SDK, v5.0 and later

    5.Run...
    8/21/2006

    长见识了

    刚刚用JBuiler 2005+Tomcat开发 Struts ,害我搞了一个小时,我想程序我都验证了是正确的,怎么会报错呢,最后发现问题的原因:
    JBuiler2005只能带JDK1.4+Tomcat 5.0,搞了JBuiler 2005自动给你调下来,导致报main函数错误.
    因为以前是用Eclipse开发,呵呵,头一回用JBuilder 2005,看者见笑了.
    因为有错误而去找出错误的原因,然后解决问题.开心.
     
    PostScript:据同事说,JBuilder 2006能带最新的配置.
    8/2/2006

    15-Year-Plan

    The First five years’ aim is to be a Project Manager.

    The Second five years’ aim is to be a CTO.

    The Third five years’ aim is to go to England or U.S.A.

    I want to drive myself car after 5 years.

    When I am 28,I plan to marry with Zhouzhou.

    After 5 years,I will own myself house.Mine and Zhouzhou’s.

    When I have implemented the Third five years’ aim ,I will be 38-year-old.

    38 years old ,Oh,I am still young.Isn’t it?

    I really love you,Zhouzhou!

    I love you very much ,Dad! Are you OK in the heaven? Maybe I can see you smile on my way home,because of your son is the best now !That’s right.

    I wish you happy every time. I miss you every day until now,Dad!

    Now I want to cry loudly,but I know you’ll say: You are a man,You CAN NOT cry!

                                                                                                                                                                              Steven                     

                                                                                                                                                               Written On 08/02/2006 4:54

    7/24/2006

    思念

    这几天经常梦见爸爸,也许是思念太多的缘故。
    反正人就是这样,只有当失去了才会想起在一起的好。
    我现在除了思念与记忆和照片。还是思念。
    我是个很重感情的人,失去的太突然了。一时还没缓过神来。
     
    6/30/2006

    回家

    今天要迅速结束战斗,回家。

    6/8/2006

    爸,你在天堂还好吗?

        孙锦良,一九五二年四月二十八号(阴历四月初五)出生,中共党员, 送信途中不幸受伤退伍。
    二零零六年六月三号(阴历五月初八)00:56因心肌梗塞在江苏省常熟市新区医院去世,享年五十五岁。
    5/22/2006

    本周为第15周

    已经在半山腰上了。
    5/21/2006

    How servlet containers work(IV)

    Application 2

    There is a serious problem in the first application. In the ServletProcessor1 class' process method, we upcast the instance of ex02.pyrmont.Request to javax.servlet.ServletRequest, passing it as the first argument to the servlet's service method. We also upcast the instance of ex02.pyrmont.Response to javax.servlet.ServletResponse and pass it as the second argument to the servlet's service method.

    try {
       servlet = (Servlet) myClass.newInstance();
       servlet.service((ServletRequest) request, (ServletResponse) response);
    }

    This compromises security. Servlet programmers who know the internal workings of our servlet container can downcast the ServletRequest and ServletResponse instances back to Request and Response and call their public methods. Having a Request instance, they can call its parse method. Having a Response instance, they can call its sendStaticResource method.

    You cannot make the parse and sendStaticResource methods private, because they will be called from other classes in the ex02.pyrmont package. However, these two methods are not supposed to be available from inside of a servlet. One solution is to give both Request and Response classes a default access modifier, so that they cannot be used from outside the ex02.pyrmont package. However, there is a more elegant solution: using facade classes.

    In this second application, we add two facade classes:RequestFacade and ResponseFacade. The RequestFacade class implements the ServletRequest interface and is instantiated by passing a Request instance, which it assigns to a ServletRequest object reference in its constructor. The implementation of each method in the ServletRequest interface invokes the corresponding method of the Request object, but the ServletRequest object itself is private and cannot be accessed from outside the class. Instead of upcasting the Request object to ServletRequest and passing it to the service method, we construct a RequestFacade object and pass it to the service method. The servlet programmer can still downcast the ServletRequest instance back to the RequestFacade; however, he can only access the methods available in the ServletRequest interface. Now, the parseUri method is safe.

    Listing 2.5 shows the incomplete RequestFacade class.

    Listing 2.5. The RequestFacade class

    package ex02.pyrmont;
    
    public class RequestFacade implements ServletRequest {
        private ServletRequest request = null;
    
        public RequestFacade(Request request) {
            this.request = request;
        }
    
        /* implementation of the ServletRequest*/
        public Object getAttribute(String attribute) {
            return request.getAttribute(attribute);
        }
    
        public Enumeration getAttributeNames() {
            return request.getAttributeNames();
        }
    
        ...
    }

    Notice the constructor of RequestFacade. It accepts a Request object but immediately assigns it to the private servletRequest object reference. Notice also that each method in the RequestFacade class invokes the corresponding method in the ServletRequest object.

    The same applies to the ResponseFacade class.

    Here are the classes used in Application 2:

    • HttpServer2
    • Request
    • Response
    • StaticResourceProcessor
    • ServletProcessor2
    • Constants

    The HttpServer2 class is similar to HttpServer1, except that it uses ServletProcessor2 in its await method, instead of ServletProcessor1:

    if (request.getUri().startsWith("/servlet/")) {
       ServletProcessor2 processor = new ServletProcessor2();
       processor.process(request, response);
    }
    else {
        ...
    }

    The ServletProcessor2 class is similar to ServletProcessor1, except in the following part of the process method:

    Servlet servlet               = null;
    RequestFacade requestFacade   = new RequestFacade(request);
    ResponseFacade responseFacade = new ResponseFacade(response);
    
    try {
        servlet = (Servlet) myClass.newInstance();
        servlet.service((ServletRequest) requestFacade, 
            (ServletResponse) responseFacade);
    }

    Compiling and Running the Application

    To compile the application, type the following from the working directory.

    javac -d . -classpath ./lib/servlet.jar src/ex02/pyrmont/*.java

    To run the application on Windows, type the following command from the working directory:

    java -classpath ./lib/servlet.jar;./ ex02.pyrmont.HttpServer2

    In Linux, use a semicolon to separate between libraries.

    java -classpath ./lib/servlet.jar:./ ex02.pyrmont.HttpServer2

    You can use the same URLs as Application1 to receive the same result.

    Summary

    This article discussed a simple servlet container that can be used to serve static resources, as well as to process servlets as simple as PrimitiveServlet. It also provided background information on the javax.servlet.Servlet interface.

     

     

    How servlet containers work(III)

    The ServletProcessor1 Class

    The ServletProcessor1 class processes HTTP requests for servlets. It is surprisingly simple, consisting only of the process method. This method accepts two arguments: an instance of javax.servlet.ServletRequest and an instance of javax.servlet.ServletResponse. The process method also constructs a java.net.URLClassLoader object and uses it to load the servlet class file. Upon obtaining a Class object from the class loader, the process method creates an instance of the servlet and calls its service method.

    The process method is given in Listing 2.4.

    Listing 2.4. The ServletProcessor1 class' process method

    public void process(Request request, Response response) {
        String uri            = request.getUri();
        String servletName    = uri.substring(uri.lastIndexOf("/") + 1);
        URLClassLoader loader = null;
    
        try {
            // create a URLClassLoader
            URLStreamHandler streamHandler = null;
    
            URL[] urls        = new URL[1];
            File classPath    = new File(Constants.WEB_ROOT);
            String repository = (new URL("file", null, 
                classPath.getCanonicalPath() + File.separator)).toString() ;
            urls[0]           = new URL(null, repository, streamHandler);
            loader            = new URLClassLoader(urls);
        }
        catch (IOException e) {
            System.out.println(e.toString() );
        }
    
        Class myClass = null;
    
        try {
            myClass = loader.loadClass(servletName);
        }
        catch (ClassNotFoundException e) {
            System.out.println(e.toString());
        }
    
        Servlet servlet = null;
        try {
            servlet = (Servlet) myClass.newInstance();
            servlet.service((ServletRequest) request, (ServletResponse) response);
        }
        catch (Exception e) {
            System.out.println(e.toString());
        }
        catch (Throwable e) {
            System.out.println(e.toString());
        }
    }

    The process method accepts two arguments: an instance of ServletRequest and an instance of ServletResponse. From the ServletRequest, it obtains the URI by calling the getRequestUri method:

    String uri = request.getUri();

    Remember that the URI is in the following format:

    /servlet/servletName

    where servletName is the name of the servlet class.

    To load the servlet class, we need to know the servlet name from the URI, which we do using the next line of the process method:

    String servletName = uri.substring(uri.lastIndexOf("/") + 1);

    Next, the process method loads the servlet. To do this, you need to create a class loader and tell this class loader the class' location. This servlet container directs the class loader to look in the directory pointed by Constants.WEB_ROOT. WEB_ROOT points to the webroot/ directory under the working directory.

    To load a servlet, use the java.net.URLClassLoader class, which is an indirect child class of java.lang.ClassLoader. Once you have an instance of the URLClassLoader class, use its loadClass method to load a servlet class. Instantiating the URLClassLoader class is straightforward. This class has three constructors, the simplest one being:

    public URLClassLoader(URL[] urls);

    where urls is an array of java.net.URL objects pointing to the locations on which searches will be conducted when loading a class. Any URL that ends with a / is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a .jar file, which will be downloaded and opened as needed.

    In a servlet container, the location where a class loader can find servlet classes is called a repository.

    In our application, there is only one location in which the class loader must look — the webroot/ directory under the working directory. Therefore, we start by creating an array of a single URL. The URL class provides several constructors, so there are many ways to construct a URL object. For this application, I used the same constructor used in another class in Tomcat. The constructor has the following signature:

    public URL(URL context, String spec, URLStreamHandler hander)
        throws MalformedURLException

    You can use this constructor by passing a specification for the second argument and null for both the first and the third arguments. However, there is another constructor that accepts three arguments:

    public URL(String protocol, String host, String file)
        throws MalformedURLException

    Thus, the compiler will not know which constructor you mean if you write the following:

    new URL(null, aString, null);

    You can get around this by telling the compiler the type of the third argument, like this:

    URLStreamHandler streamHandler = null;
    new URL(null, aString, streamHandler);

    For the second argument, pass the String containing the repository (the directory where servlet classes can be found). Create it with this code:

    String repository = (new URL("file", null,
        classPath.getCanonicalPath() + File.separator)).toString();

    Combining everything, here is the part of the process method that constructs the right URLClassLoader instance:

    // create a URLClassLoader
    URLStreamHandler streamHandler = null;
    
    URL[] urls        = new URL[1];
    File classPath    = new File(Constants.WEB_ROOT);
    String repository = (new URL("file", null, 
        classPath.getCanonicalPath() + File.separator)).toString() ;
    urls[0]           = new URL(null, repository, streamHandler);
    loader            = new URLClassLoader(urls);

    The code that forms a repository comes from the createClassLoader method in org.apache.catalina.startup.ClassLoaderFactory, and the code for forming the URL is taken from the addRepository method in the org.apache.catalina.loader.StandardClassLoader class. However, you don't have to worry about these classes at this stage.

    Having a class loader, you can load a servlet class using the loadClass method:

    Class myClass = null;
    try {
        myClass = loader.loadClass(servletName);
    }
    catch (ClassNotFoundException e) {
        System.out.println(e.toString());
    }

    Next, the process method creates an instance of the servlet class loaded, downcasts it to javax.servlet.Servlet, and invokes the servlet's service method:

    Servlet servlet = null;
    try {
        servlet = (Servlet) myClass.newInstance();
        servlet.service((ServletRequest) request, (ServletResponse) response);
    }
    catch (Exception e) {
        System.out.println(e.toString());
    }
    catch (Throwable e) {
        System.out.println(e.toString());
    }

    Compiling and Running the Application

    To compile the application, type the following from the working directory:

    javac -d . -classpath ./lib/servlet.jar src/ex02/pyrmont/*.java

    To run the application on Windows, type the following command from the working directory:

    java -classpath ./lib/servlet.jar;./ ex02.pyrmont.HttpServer1

    in Linux, use a colon to separate between libraries.

    java -classpath ./lib/servlet.jar:./ ex02.pyrmont.HttpServer1

    To test the application, type the following in the URL or address box of your browser:

    http://localhost:8080/index.html

    or

    http://localhost:8080/servlet/PrimitiveServlet

    You will see the following text in your browser:

    Hello. Roses are red.

    Note that you can't see the second string (Violets are blue) because only the first string is flushed to the browser. The applications accompanying the later chapters of the How Tomcat Works book show you how to fix this problem.