![]() |
![]() |
Java EE6 Weblogic Exercice 3De $1Table des matières
IntroductionIn this exercice we will play a little more with relations, relations attributes, bidirectional relations, the removal of linked entities, etc. Then we will use JMS and Message Driven beans, by adding to the previous exercice the possibility to process Bank Account operations asynchronously by sending messages. We will also play with some other goodies like EJBTimers and Asyncrhonous method calls. Play more with the relations in our exampleTry to remove an operation by adding a remove button on the right of the table of operationsLike we did in exercice 1, code a way to remove an operation from the table of operations. There is a trap ! Try to remove an account, what happens to the operations ?Ah ? And what happens if you change the CASCADE annotation to @OneToMany(cascade = { }... in Account.java, try again to remove an Account. Just remove the CASCADETYPE attribute. Change the Account-Operations to a bidirectional relationshipLook at the example in the course and change the unidirectional relation between accounds and operations into a bidirectional one. Try to display from the list of operations the detail of the account the operation belongs to. Add a new n-n relation between customers and bank accountsNow, we are not going to create all the JSP/Servlet code for testing this as it would take too much time (although some of you may finish in advance, this could be an exercice)... We would like to modelize the fact that a Customer may have several bank accounts and a bank account may be owned by more than one Customer at a time (like joint accounts, or family accounts). For the exercice, we will say thet a Customer has an id, and a name, plus a list of Accounts. In that case, the Account no more has a "name" of owner, but instead, the names of the different owners would have to be found in every Customer's name property, in the list of Customers associated to an Account. So, create a n-n relation between Customers and Accouts, and try to associate some customers to accounts and vide-versa in the AccountFace createTestData() method. You will check in the database that the data you inserted are correct. Add a JMS destination queue to Weblogic, write a MDB and a Servlet to testThis is the tricky part... Follow the instruction from the Weblogic / Java EE6 FAQ and Guides, follow the section "Use JMS and a Message Driven Bean on Weblogic" entirely. You will add the Message Driven Bean and the Servlet in the EJB project from exercice 2. Try to execute the Servlet to see the results. Adapt the Message Driven Bean and the Servlet so that it can be used to send Bank Account OrdersWrite a new java class called BankAccountOrderIn a new package "beans" write a new class that describes an order we will send as a message to the Message Driven Bean, that will read the message, decode the object received and then delegate the treatment to the AccountFace session bean. For example, if you send a "createAccount" order with an inital balance of 10.000 and an owner name equals to "Michel Buffa", then when the MDB gets this message, it will call the AccountFacade's create() method for creating a new bank Account. Etc. The BankAccountOrder bean should have these properties: order, ammount, name, id1, id2. Not all properties will be necessarily used depending on the value of the order (create, remove, transfert, add, remove, etc.) It should implements Serializable as instances of BankAccountOrder will be sent through the network as ObjectMessage content. Adapt the code from the Servlet in order to send instances of BankAccountOrders within JSM ObjectMessagesThe example you wrote from the previous section sends TextMessages. Modify the code from the Servlet in order to send an BankAccountOrder. Instead of sending TextMessages, you will have to send ObjectMessages. Just look at the current code of the two methods that send messages: private TextMessage createJMSMessageForjmsLoggingMessages(Session session, String messageData) throws JMSException { TextMessage message = session.createTextMessage(); message.setText(messageData); return message; } Just change the "String messageData" into "BankAccountOrder messageData" in the input parameters of these methods, change TextMessage by ObjectMessage everywhere. Adapt the message driven bean so that it can handle ObjectMessages as well as TextMessagesModify the content of the onMessage(Message message) method by adding a new test: if (message instance of ObjectMessage) { ... //get the object inside the message .... // Cast it in AccountOrderObjects .... // decode it (look at the value of the "order" property, get other properties... .... // Call the AccountFacade to do the work... } Make a rapid test to check that more than one instance of the message driven bean may be createdFor this test, we will simulate a process that takes a long time. Add this code to the message driven bean in the previous code... // at the beginning... System.out.println("Just got an order to proceed, will take some time..."); // call account facad ... // simulate a 7s treatment Thread.sleep(7000); // Print end of treatment System.out.println("Order processing finished"); Add the required try.. catch... test it. Then when you invoke the servlet, press the reload button a few times quickly in your web browser so that several JMS messages are sent in a short ammount of time. Look at the console logs... You should see something like: Just got an order to proceed, will take some time... Just got an order to proceed, will take some time... Just got an order to proceed, will take some time... Just got an order to proceed, will take some time... Just got an order to proceed, will take some time... Just got an order to proceed, will take some time... Order processing finished Just got an order to proceed, will take some time... Order processing finished Order processing finished Just got an order to proceed, will take some time... Just got an order to proceed, will take some time... Order processing finished Order processing finished This means that each time a message arrived processing has been done in parallel (by different instances) Try the @Asynchronous annotationThis time, you will run the Servlet you developped for exercice 2, the one with the forms for creating or displaying new accounts. Modify the createTestData() method by adding a Thread.sleep(7000) too so that executing this method takes 7s. Add a link in the Servlet for calling this method when the link is clicked and try clicking on it. Hmmm the jsp page with the list of Accounts is displayed seven seconds later as we have been actively waiting for the createTestData() to perform. Now add just the @Asynchronous annotation before the method. Do the same test. Huh ! Try the new EJBTimers from EJB 3.1 specificationJust add to the "sessions" package of your project a new class of type "EJB timer", call it MyTimer. This will pop up a dialog in which you will be able to configure the schedule for your timer. The syntax for specifying when your timer will be called is similar to the one used by Unix's crontabs. A typical schedule: second="*/10", minute="*", hour="8-23", dayOfWeek="Mon-Fri", dayOfMonth="*", month="*", year="*", info="MyTimer" This is the default value proposed by the Eclipse dialog for creating EJB timers, it means:
The class you should get looks like that: package sessions; Notice that an EJB timer is a stateless session bean (@Stateless), that the method that should be called at given period of times is preceeded by a @Schedule annotation that is parameterized by a schedule definition. Deploy this project and look at the console, you should see some messages in the console, and every 10s, a new message should appear... Play with the bean validation APIBean Validation is a new specification added to the Java EE 6 platform, the JSR-303 specification. It defines an extensible validation constraints mechanism, with a pre-defined set of constraints that can be specified on field, method, type, or annotations. It also defines a validation facility for the Java application developer. The constraints can be specified on a JPA entity and the validation facility ensure these are met during the pre-persist, pre-update, and pre-remove lifecycle events. These constraints can also be used on “backing beans” for forms displayed by JSF. This ensures that the data entered in the form meets the validation criteria. Here is a good presentation of the bean validation API: http://fr.slideshare.net/openwms/jsr...on-api-3415687 Important things to notice is that this API proposes the same mechanisms to validate in the presentation layer (in JSF2 pages), in the business layer (managed beans, EJBs, etc), and in the data layer (entity classes). the Java Bean validation API is part of JavaEE6 and you do not have to add any external libs to your project. Let's try a simple example: in the entity bean Manufacturer from the first example of day one, add this line before the "name" : @Size(min=3 max=10) private String name;
Now, try to insert a manufacturer whose name is shorter than 3 characters or longer than 10 characters, you should see such an exception: Caused By: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details. Notice that the validation has been performed by the persistence manager in that case. While the bean validation API can be used without entity classes, in regular java beans, when ussed in entity classes it involves the persistence layer: the validation has been done in some generated code that implements the @PrePersist callback. Possible values for predefined constraint annotations are (look at this picture: http://miageprojet2.unice.fr/@api/de...nnotations.jpg) INSERT SCREENSHOT Notice that it is possible to create your own constraints, or use the bean validation API in a context where code injection is not always possible, like in standalone clients, etc. See this blog post (in french) for such examples: http://blog.octo.com/jsr-303-bean-va...tat-des-lieux/ Look at bigger examplesExample 1Here is more advanced example of a bank account management program that uses EJBs. It has been written by a student from the Univiersity of Nice so it is not guaranteed that this code is top clean state of the art, but it shows how we could go from the small toy examples we built to a litlle bigger application.
Now, look at the code of the EJB part, of the Web part. Notice that there is not @Singleton, @Startup EJB for populating the database this time. The project has been written before EJB 3.1x proposed this feature. SO try to see where the database is populated and what method has been used to populate it at first use. Can you criticize this method ? What method could have been used (not @Singleton) instead ? |
Powered by MindTouch Deki Open Source Edition v.8.08 |