Wednesday, October 21, 2009

Using Code Examples










Using Code Examples



This book is here to help you get your job done. In general, you may
use the code in this book in your programs and documentation. You do
not need to contact us for permission unless you're
reproducing a significant portion of the code. For example, writing a
program that uses several chunks of code from this book does not
require permission. Selling or distributing a CD-ROM of examples from
O'Reilly books does require
permission. Answering a question by citing this book and quoting
example code does not require permission. Incorporating a significant
amount of example code from this book into your
product's documentation does
require permission.



We appreciate, but do not require, attribution. An attribution
usually includes the title, author, publisher, and ISBN. For example:
"Jakarta Struts Cookbook by
Bill Siggelkow. Copyright 2005 O'Reilly Media, Inc.,
0-596-00771-X."



If you feel your use of code examples falls outside fair use or the
permission given above, feel free to contact us at
permissions@oreilly.com.











    Removing Hypersonic









    Removing Hypersonic


    Hypersonic is a great database for testing an application, but it isn't production ready. In Chapter 4, you saw how to switch to another database. If you aren't using Hypersonic, you can remove the entire service. Hypersonic doesn't listen for connections from the outside world unless you ask it to, so you don't need to worry about securing it. However, you might not want an extra relational database hanging around in memory. It's fairly lightweight, but you'll probably be better off just getting rid of it.



    How do I do that?


    The hsqldb-ds.xml file not only configures the Hypersonic datasources, but also it has the MBeans that control the entire embedded database service. Removing this file will remove all traces of Hypersonic.


    It sounds trivial, and it would be except that several other services depend on Hypersonic. We'll go through the changes now, assuming you have created a MySQL database as shown in Chapter 4, and that the ToDo application is already switched over to using that.


    The first service is the EJB timer service, in ejb-deployer.xml. You should replace the reference to DefaultDS with a reference to the correct datasource. In Chapter 4, we chose the name MySqlDS. The change is simple:



    <!-- A persistence policy that persists timers to a database -->
    <mbean code="org.jboss.ejb.txtimer.DatabasePersistencePolicy"
    name="jboss.ejb:service=EJBTimerService,persistencePolicy=database">
    <!-- DataSource JNDI name -->
    <depends optional-attribute-name="DataSource">
    jboss.jca:service=DataSourceBinding,name=MySqlDS
    </depends>

    <!-- The plugin that handles database persistence -->
    <attribute name="DatabasePersistencePlugin">
    org.jboss.ejb.txtimer.GeneralPurposeDatabasePersistencePlugin
    </attribute>
    </mbean>



    JMS also requires persistence changes to be made. If you aren't using JMS and you chose to remove it from your configuration, you can stop here. Otherwise, go to the deploy/jms directory and look for hsqldb-jdbc2-service.xml and hsqldb-jdbc-state-service.xml.


    hsqldb-jdbc2-service.xml controls message persistence. You can remove it completely and replace it with a database-specific file from docs/examples/jms. For MySQL, copy mysql-jdbc2-service.xml into the jms directory.


    hsqldb-jdbc-state-service.xml isn't quite so simple. There are no database-specific templates for this. You'll need to update the datasource dependency manually:



    <mbean code="org.jboss.mq.sm.jdbc.JDBCStateManager"
    name="jboss.mq:service=StateManager">
    <depends optional-attribute-name="ConnectionManager">
    jboss.jca:service=DataSourceBinding,name=MySqlDS
    </depends>

    <!-- ... -->
    </mbean>



    This datasource reference needs to be the same as the datasource you saw earlier, in the jbossmq security domain in login-config.xml. You'll want to update that now too:



    <application-policy name="jbossmq">
    <authentication>
    <login-module
    code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
    flag="required">
    <module-option name="unauthenticatedIdentity">guest
    </module-option>
    <module-option name="dsJndiName">java:/MySqlDS</module-option>
    <module-option name="principalsQuery">
    SELECT PASSWD FROM JMS_USERS WHERE USERID=?
    </module-option>
    <module-option name="rolesQuery">
    SELECT ROLEID, 'Roles' FROM JMS_ROLES WHERE USERID=?
    </module-option>
    </login-module>
    </authentication>
    </application-policy>



    The final dependency on DefaultDS is uuid-key-generator.sar. If you aren't using the JBoss UUID key generator, remove this service from the deploy directory. If you are, you'll need to update the META-INF/jboss-service.xml file to reference the preferred datasource:



    <mbean code="org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory"
    name="jboss:service=KeyGeneratorFactory,type=HiLo">
    <!-- ... -->
    <depends optional-attribute-name="DataSource">
    jboss.jca:service=DataSourceBinding,name=MySqlDS
    </depends>

    <!-- ... -->
    </mbean>



    Unfortunately, this service is not provided in exploded form, so you'll have you unpack the archive to get to it.




    What just happened?


    You removed Hypersonic and updated, or removed, the services that depend on it. All of the persistent services will write their tables into the new database. If you've kept them around and restarted JBoss, you should find several new database tables in your external database:



    mysql> show tables in jbossdb;
    +-------------------+
    | Tables_in_jbossdb |
    +-------------------+
    | Comment |
    | HILOSEQUENCES |
    | JMS_ROLES |
    | JMS_SUBSCRIPTIONS |
    | JMS_TRANSACTIONS |
    | JMS_USERS |
    | TIMERS |
    | Task |
    | jms_messages |
    +-------------------+
    9 rows in set (0.14 sec)



    You could have saved yourself some trouble by creating a replacement DefaultDS. Then it wouldn't have been necessary to change all the datasource references. However, it's important to be explicit about your configuration in a production machine. The extra effort is worth the peace of mind of knowing that all your persistent services are configured correctly.










      Section 2.8. Lists and Tuples











      2.8. Lists and Tuples


      Lists and tuples can be thought of as generic "arrays" with which to hold an arbitrary number of arbitrary Python objects. The items are ordered and accessed via index offsets, similar to arrays, except that lists and tuples can store different types of objects.


      There are a few main differences between lists and tuples. Lists are enclosed in brackets ( [ ] ) and their elements and size can be changed. Tuples are enclosed in parentheses ( ( ) ) and cannot be updated (although their contents may be). Tuples can be thought of for now as "read-only" lists. Subsets can be taken with the slice operator ( [] and [ : ] ) in the same manner as strings.


        >>> aList = [1, 2, 3, 4]
      >>> aList
      [1, 2, 3, 4]
      >>> aList[0]
      1
      >>> aList[2:]
      [3, 4]
      >>> aList[:3]
      [1, 2, 3]
      >>> aList[1] = 5
      >>> aList
      [1, 5, 3, 4]


      Slice access to a tuple is similar, except it cannot be modified:


        >>> aTuple = ('robots', 77, 93, 'try')
      >>> aTuple
      ('robots', 77, 93, 'try')
      >>> aTuple[:3]
      ('robots', 77, 93)
      >>> aTuple[1] = 5
      Traceback (innermost last):
      File "<stdin>", line 1, in ?
      TypeError: object doesn't support item assignment


      You can find out a lot more about lists and tuples along with strings in Chapter 6.












      7.3. Good Routine Names










       < Free Open Study > 







      7.3. Good Routine Names



      A good name for a routine clearly describes everything the routine does. Here are guidelines for creating effective routine names:



      Cross-Reference





      For details on naming variables, see Chapter 11, "The Power of Variable Names."




      Describe everything the routine does In the routine's name, describe all the outputs and side effects. If a routine computes report totals and opens an output file, ComputeReportTotals() is not an adequate name for the routine. ComputeReportTotalsAndOpen-OutputFile() is an adequate name but is too long and silly. If you have routines with side effects, you'll have many long, silly names. The cure is not to use less-descriptive routine names; the cure is to program so that you cause things to happen directly rather than with side effects.



      Avoid meaningless, vague, or wishy-washy verbs Some verbs are elastic, stretched to cover just about any meaning. Routine names like HandleCalculation(), PerformServices(), OutputUser(), ProcessInput(), and DealWithOutput() don't tell you what the routines do. At the most, these names tell you that the routines have something to do with calculations, services, users, input, and output. The exception would be when the verb "handle" was used in the specific technical sense of handling an event.



      Sometimes the only problem with a routine is that its name is wishy-washy; the routine itself might actually be well designed. If HandleOutput() is replaced with FormatAndPrintOutput(), you have a pretty good idea of what the routine does.




      In other cases, the verb is vague because the operations performed by the routine are vague. The routine suffers from a weakness of purpose, and the weak name is a symptom. If that's the case, the best solution is to restructure the routine and any related routines so that they all have stronger purposes and stronger names that accurately describe them.



      Don't differentiate routine names solely by number One developer wrote all his code in one big function. Then he took every 15 lines and created functions named Part1, Part2, and so on. After that, he created one high-level function that called each part. This method of creating and naming routines is especially egregious (and rare, I hope). But programmers sometimes use numbers to differentiate routines with names like OutputUser, OutputUser1, and OutputUser2. The numerals at the ends of these names provide no indication of the different abstractions the routines represent, and the routines are thus poorly named.



      Make names of routines as long as necessary Research shows that the optimum average length for a variable name is 9 to 15 characters. Routines tend to be more complicated than variables, and good names for them tend to be longer. On the other hand, routine names are often attached to object names, which essentially provides part of the name for free. Overall, the emphasis when creating a routine name should be to make the name as clear as possible, which means you should make its name as long or short as needed to make it understandable.



      To name a function, use a description of the return value A function returns a value, and the function should be named for the value it returns. For example, cos(), customerId.Next(), printer.IsReady(), and pen.CurrentColor() are all good function names that indicate precisely what the functions return.



      Cross-Reference





      For the distinction between procedures and functions, see Section 7.6, "Special Considerations in the Use of Functions," later in this chapter.




      To name a procedure, use a strong verb followed by an object A procedure with functional cohesion usually performs an operation on an object. The name should reflect what the procedure does, and an operation on an object implies a verb-plus-object name. PrintDocument(), CalcMonthlyRevenues(), CheckOrderlnfo(), and RepaginateDocument() are samples of good procedure names.



      In object-oriented languages, you don't need to include the name of the object in the procedure name because the object itself is included in the call. You invoke routines with statements like document.Print(), orderInfo.Check(), and monthlyRevenues.Calc(). Names like document.PrintDocument() are redundant and can become inaccurate when they're carried through to derived classes. If Check is a class derived from Document, check.Print() seems clearly to be printing a check, whereas check.PrintDocument() sounds like it might be printing a checkbook register or monthly statement, but it doesn't sound like it's printing a check.



      Use opposites precisely Using naming conventions for opposites helps consistency, which helps readability. Opposite-pairs like first/last are commonly understood. Opposite-pairs like FileOpen() and _lclose() are not symmetrical and are confusing. Here are some common opposites:



      Cross-Reference





      For a similar list of opposites in variable names, see "Common Opposites in Variable Names" in Section 11.1.




      add/remove

      increment/decrement

      open/close

      begin/end

      insert/delete

      show/hide

      create/destroy

      lock/unlock

      source/target

      first/last

      min/max

      start/stop

      get/put

      next/previous

      up/down

      get/set

      old/new

       




      Establish conventions for common operations In some systems, it's important to distinguish among different kinds of operations. A naming convention is often the easiest and most reliable way of indicating these distinctions.



      The code on one of my projects assigned each object a unique identifier. We neglected to establish a convention for naming the routines that would return the object identifier, so we had routine names like these:







      employee.id.Get()

      dependent.GetId()

      supervisor()

      candidate.id()





      The Employee class exposed its id object, which in turn exposed its Get() routine. The Dependent class exposed a GetId() routine. The Supervisor class made the id its default return value. The Candidate class made use of the fact that the id object's default return value was the id, and exposed the id object. By the middle of the project, no one could remember which of these routines was supposed to be used on which object, but by that time too much code had been written to go back and make everything consistent. Consequently, every person on the team had to devote an unnecessary amount of gray matter to remembering the inconsequential detail of which syntax was used on which class to retrieve the id. A naming convention for retrieving ids would have eliminated this annoyance.












         < Free Open Study > 



        Section 26.6.&nbsp; Singletons










        26.6. Singletons


        In general, Eclipse is able to concurrently run multiple versions of the same plug-in. That is, org.eclipsercp.hyperbola version 1.0 and 2.0 can both be installed and running at the same time. This is part of the power of the Runtime's component model. Dependent plug-ins are bound to particular versions of their prerequisites and see only the classes supplied by them.


        There are cases, however, where there really should be only one version of a given plug-in in the system. For example, SWT makes certain assumptions about its control over the display and main thread. SWT cannot cohabitate with other SWTs. More generally, this occurs wherever one plug-in expects to have exclusive access to a global resource, whether it be a thread, an OS resource, a network port, or the extension registry namespace.


        To address this, OSGi allows a bundle to be declared as a singleton. The bundle in the example below is marked as a singleton. This tells OSGi to resolve at most one version of the bundle. All other version constraints in the system are then matched against the chosen singleton version.


        org.eclipse.core.runtime/MANIFEST.MF
        Bundle-SymbolicName: org.eclipse.core.runtime;singleton:=true
        Bundle-Version: 3.1.0


        The most common reason to mark a plug-in as a singleton is that it declares extensions or extension points. The extension registry namespace is a shared resource that is populated by bundle ids. If we allowed multiple versions of the same bundle to contribute to the registry, interconnections would be ambiguous.


        By default, bundles that declare extensions or extension points but do not have a MANIFEST.MF are marked as singletons. If you have a MANIFEST.MF, you should annotate it accordingly.












        Walking Through Scenarios



        [ Team LiB ]





        Walking Through Scenarios


        To cross-check all these decisions, we have to constantly step through scenarios to confirm that we can solve application problems effectively.


        Sample Application Feature: Changing the Destination of a Cargo


        Occasionally a Customer calls up and says, "Oh no! We said to send our cargo to Hackensack, but we really need it in Hoboken." We are here to serve, so the system is required to provide for this change.


        Delivery Specification is a VALUE OBJECT, so it would be simplest to just to throw it away and get a new one, then use a setter method on Cargo to replace the old one with the new one.


        Sample Application Feature: Repeat Business


        The users say that repeated bookings from the same Customers tend to be similar, so they want to use old Cargoes as prototypes for new ones. The application will allow them to find a Cargo in the REPOSITORY and then select a command to create a new Cargo based on the selected one. We'll design this using the PROTOTYPE pattern (Gamma et al. 1995).


        Cargo is an ENTITY and is the root of an AGGREGATE. Therefore, it must be copied carefully; we need to consider what should happen to each object or attribute enclosed by its AGGREGATE boundary. Let's go over each one:



        • Delivery History:
          We should create a new, empty one, because the history of the old one doesn't apply. This is the usual case with ENTITIES inside the AGGREGATE boundary.


        • Customer Roles:
          We should copy the Map (or other collection) that holds the keyed references to Customers, including the keys, because they are likely to play the same roles in the new shipment. But we have to be careful not to copy the Customer objects themselves. We must end up with references to the same Customer objects as the old Cargo object referenced, because they are ENTITIES outside the AGGREGATE boundary.


        • Tracking ID:
          We must provide a new Tracking ID from the same source as we would when creating a new Cargo from scratch.


        Notice that we have copied everything inside the Cargo AGGREGATE boundary, we have made some modifications to the copy, but we have affected nothing outside the AGGREGATE boundary at all.





          [ Team LiB ]



          Section 13.6. Summary











          13.6. Summary


          In this chapter, we covered some of the history of Ruby on Rails, including the fact that Ruby on Rails is separated into Ruby and Rails. From there, we covered the process of installing Ruby and then installing Rails and viewing the default page. Then we covered how to create an empty project and fire up the included WEBrick web server and access a MySQL database, albeit with a little difficulty. In essence, the purpose of this chapter is to point the reader in the right direction when in search of an environment that supports Ajax.