Scrigroup - Documente si articole

Username / Parola inexistente      

Home Documente Upload Resurse Alte limbi doc  

AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows

AspAutocadCDot netExcelFox proHtmlJava
LinuxMathcadPhotoshopPhpSqlVisual studioWindowsXml

Web Applications


+ Font mai mare | - Font mai mic


Trimite pe Messenger
AWT Peer Interfaces
Web Applications
Color, Font, Images, And Shapes
Windowing Components And Layout Classes
Applets And Graphics
Handling URLs And Networking Exceptions
The Component Class
Data Structures And Random Number Generation
AWT Image Processing
Network And Sockets

Web Applications

Chapter 1 outlined  the concepts   of MVC and gave a brief discussion   of web frameworks. The main  reason  for that discussion   was to help you understand any major  web frame-

work that has come  out since  2000. In this chapter, however, I want  to go over two things: a more  detailed  review of the web server  side, and an introduction to the web applica- tions used  in this book.

The fundamental    component of any Java web application   today  is the servlet.  It is the common   denominator, and back in the ’90s many  of us wrote  entire  applications    using only servlets.  In this chapter, I will quickly cover what  a servlet  is and then we will get into some  actual  web application   design.  You will investigate   a few implementation     patterns. As I cover each  of these  implementation     patterns used  in Seam,  I will highlight  (when appropriate) the similarities   and differences   as compared   to the Struts framework.   This will expose  you to more  Seam code  and should  prepare you for Seam coding  in Chapter  5.

Three  major  web applications   are used  in this book. In this chapter, you will learn about the main  applications   we are going to build  throughout this book.


Servlets are the basis  for any web application   written today.  However,  they may be one of the least known  APIs for new Java developers   who started their  web development    by using a framework  such  as Struts. The Java Community   Process  ( JCP) designed   the

Servlet specification   in 1997 as JSR 53. The most  current version  of it is defined  by JSR 154

and was released  in September 2005.

A Servlet object  in the most  basic  sense  allows for communication     between a client and a server  via the Hypertext  Transfer  Protocol  (HTTP). The most  common   application of this is of course  dynamic  web pages,  although   you will find client-side   applets  talking to servers  in the same  manner as well.

The Servlet class file resides  in the javax.servlet package.  Because  servlets  are a specification   and not a Sun implementation,     in order  to use servlets,  one relies on an individual   web container   vendor such  as JBoss (which  uses Apache Tomcat)  to imple-

ment the specification.   The most  common   implementation     of the Servlet interface  is the


HttpServlet object,  which  is the basis  for most  web frameworks.   HttpServlet will accept requests   (HttpServletRequest),     allow for a method for processing, and return a response (HttpServletResponse).    In addition,   it can keep track of a ServletContext    and HttpSession object;  I will go over that in more  detail  in a bit. The HttpServlet object  is called  by the application   server  and calls methods (doPost(..), doGet(..), service(..)) that then con- tain data to process the request.

Contexts  in Servlets

A context represents an area  where  serializable   objects  (classes  that implement are stored.  These  objects  differ mainly  in their  life cycles. Some  of the objects  are saved  indefinitely,   whereas  others  are around for just a short period of time.  In servlets  there are three contexts  by default:  the ServletContext context,  the ServletRequest    context,  and the HttpSession   context.  Each context  uses maps for storage.


The ServletContext    context  is represented by the interface  javax.servlet.ServletContext, which  you can retrieve with the getServletContext() method on the Servlet object  A ServletContext    context  contains   application   data that is not user specific.  This data can be set at any time  and will be stored  for as long as the server  is alive. The type of data that is stored  in a ServletContext    context  is usually  something   such  as names of states  or names of countries—items that are the same  for any user and generally  not too large.

ServletRequest Context

The ServletRequest    context  is represented by the interface  javax.servlet.ServletRequest, which  is passed  as a parameter to the Servlet(s) processing methods. The data that is set on ServletRequest    is typically  tied to a response   for a single round-trip to the server.  A round-trip consists  of a request  that originates   from the web page,  is sent to the servlet, and is then sent back to the web page.  After the web page has finished  rendering, ServletRequest    gets recycled.  This object  will store  data that was sent over—for  exam- ple, when  you fill out a form online  and submit  it, the data is saved  to the HttpServletRequest     object.

HttpSession Context

The HttpSession   context  is represented by the interface  javax.servlet.http.HttpSession, which  is stored  as a property on the HttpServletRequest     interface.  HttpSession   is created for the user explicitly  by the server-side   application   calling getSession() or getSession(true) on HttpServletRequest.     The HttpSession   data will persist  across  multiple

requests   to the server  on one connection.   To understand what  I mean by one connection, think  of opening  a web browser and connecting   to a server—that   represents one connec- tion to the server.  Opening  more  browser windows  will each  represent new connections to the server.

The HttpSession   data can be destroyed   in one of three ways: by explicitly  calling the invalidate() method on HttpSession,   by shutting  down  the browser window,  or by the connection   timing  out (which  is a configurable   option on HttpSession).

Closing Thoughts on Servlet Contexts

Even though  all three of these  contexts  are extremely  useful,  you cannot do everything you want  with them. However,  they provide the basis  to create  other contexts  that can be customized   to have more  functionality.   Seam,  in fact, uses seven contexts  that are all in some  ways derived  from these  three. I will touch on these  contexts  in Chapter  5 and then go into much greater  depth with them in Chapters   6 and 7. For now we will stick with these  three.

Servlets and Frameworks

One final thought about servlets  before  we go on: you can be an experienced   developer and have never  touched an HttpServlet object.  This is because  the servlet  layer is where frameworks   (in general)  start their  abstraction.   So if you are a developer   who started cod- ing after about 2002, odds  are that you have never  had to write a servlet  for a job. Even if you were developing   before  that, you probably had just one servlet  sending  you some- where  else (or for the most  part, you should  have).  However,  I wanted  this section  to give those  who are not familiar  with servlets  a chance  to review the basics.

Implementation Patterns

In this section,  I am going to present some  challenges   that arise when  designing  web applications.   Developers   face various  challenges   when  creating  web applications.   These tasks can be described   through implementation     patterns. For the experienced   devel- oper, these  patterns will seem  quite  familiar—for  example,  displaying  lists and logging on to a page.  For the entry-level developer,   these  patterns will seem  new but should seem obvious  if you have spent any decent amount of time  surfing  the Web.

Table 2-1 summarizes the patterns discussed   in this section.  Most of these  imple- mentations will be used  in this section  for finding,  updating,   and viewing restaurants in a given zip code.

Table 2-1. Presentation  Implementation    Patterns

Topic                                        Description

Displaying  dynamic  data                       We make  a request  to the server  to get the best  restaurant and save it to the request  object  to be displayed  on the page.

Requesting   and saving data                    We make  a request  to the server  to get the best  restaurant as in the first pattern. However,  the user will then be able to change  the name of the best  restaurant.

Logging in                                                                       The user passes  in a username and password for validation.

If the user is validated,  the username will be saved  to the

HttpSession   context.

Listing and viewing a page                      We display  a list of restaurants. The user can then select  one restaurant to view the details  of it.

For each pattern, I will explain  to you the task at hand and the problem we are try- ing to solve. Then  I will present a standard activity  diagram indicating   how this issue will be solved.

I will first present the Struts implementation     of it and then the Seam implementa- tion.  I decided  to use Struts for the examples  mainly  because  it is simple  to understand a Struts Action  class even if you have no knowledge  of Struts. Also, because  Struts is so prevalent in the marketplace, it will either  be familiar  or provide helpful  exposure  to the majority  of developers   out there.

Now the thing  to remember   is that these  are not 100 percent complete   code  samples. I have left out the JSPs (for Struts) and the JSF pages  (for Seam).  Also, for the Struts exam- ples I am not actually  implementing    the business   class created.  However,  the business class will get implemented    for the Seam example.  This is because  Seam essentially  skips having  to write any servlet-based   class and gets you directly  to the EJB3 page.

The purpose of these  pages  is not to give you lots of code  examples  to learn from, but to give you an ability  to compare   and contrast what  the code  looks like in Struts as com- pared to Seam.  My hope is that you will start to gain an appreciation for Seam and some of the benefits  to using  it. As you read  along  the rest of the book, we will use these  imple- mentation patterns at various  points  to cut down  on coding  time  and increase  the clarity of the code.  So for right now just look at these  patterns from an abstract   point of view of how they could  help you more.

Before diving into the patterns, you will take a look at brief explanations   of the Struts and Seam pages  that will be used  in the examples.

Understanding the Parts of Our Examples

As I said, these  examples  are going to have two Java files for them:  a Seam one and a Struts one. Because  not everyone is going to understand each,  I will present a crash course  on each  example  setup.


For those  of you who have  never  seen  Struts, think  of this as a crash  course.  If you understand a Servlet object,  you will understand an Action  class. The Action  classes very much mimic  the way a Servlet object  looks. Listing 2-1 provides an example  of an Action  class.

Listing 2-1. An Example  of a Basic Struts  Class

public class GenericStrutsAction      extends   Action   


A couple  of these  attributes should  be familiar  to youHttpServletRequest and

HttpServletResponse,    which  we have  just gone  over. The other two objects  will take a bit more  explanation.

ActionForm is a Struts object  used  to represent the request  data that the user  has sent over. This object  allows us to have  a more  concrete   implementation     that is defined in an XML file. Notice  that in the method itself, ActionForm is casted  to DynaActionForm. DynaActionForm is a DynaBean, which  are type-safe  maps. This means that in a configura- tion  file, you can specify  that this object  is being  stored  as a Boolean.  This is useful because   all objects  sent over from  the browser—whether numbers or letters—are strings by default.

Finally, you have  ActionMapping, which  is used  to look up what  page  to forward the next request  to. This allows the user  to map names to actual  JSP pages.  This way, if you decide  to change  to a different page,  you can do it in the XML file instead  of changing your code.

Throughout   the Struts examples,   I will be referring  to a business   service  that is a global  property on the Action  class. You can think  of this as an EJB that has been injected  into  the Action  class. I wont provide concrete   implementation     of these  inter- faces because   what  they specifically  do is not important. The important thing  is what the Struts page  is doing  and how it interacts   with the business   service.


Now although   it may seem  unfair  to display  a bunch of Seam pages  without  more  expla- nation,  the purpose is just to appreciate Seams simplicity.  However,  I do want  to make  a few notes about these  pages.  The classes  are all annotated with @Stateless,   which  indi- cates  that these  are all actual  stateless  session  beans (SLSBs). There  will be no plumbing code  such  as Action  or Servlet classes  to write; that is all handled by the framework.   Also the Seam objects  each  implement   an interface.  I have not provided a concrete   represen- tation of the interface,  but just assume  it contains   the same  methods that are on the Seam component itself.

Now that you have the basics  underway, Ill start showing  some  code.

Displaying   Dynamic   Data

Aside from a perfectly static  page of text, a page that is generated by dynamic  data is probably one of the most  commonly   used  types  of pages.  In this example,  we have a request  made to the server  to find the best restaurant for an inputted zip code.

Figure 2-1 shows  an activity diagram outlining  the steps  to take when  creating  this page. As you can see, after the request  is made, the server  will retrieve the name of the best

restaurant for display  on the page.  In Struts this will happen by an Action  class calling a business   service.  Listing 2-2 provides this code.

Listing 2-2. The Struts  Action for Retrieving  the Best Restaurant

public class LookupRestaurantStrutsAction       extends   Action   


Figure 2-1. Activity  diagram of a call to a stateless page

This code  is fairly straightforward,    and its steps  can be outlined  as follows:

1.  Retrieve the zip code  passed  as a request  parameter called  zipCode.

2.  Use our business   service  to look up the best restaurant by zip code.

3.  Set an attribute so we can pass back the restaurant on a request  attribute called


4.  Finally, look up the success  page and return to that page.

Although  this is not that complex,  remember   that we still have to code  and inject  the business   class for it to work, and we have basically  spent this entire  page setting  variables to be sent over and then retrieving the variables.  So now lets take a look at the Seam ver- sion of this page in Listing 2-3.

Listing 2-3. The Seam  Component   for Retrieving  the Best Restaurant



public class LookupRestaurantAction     implements   ILookupRestaurantAction


In this page we do not have to explicitly  set any variables  because  that is done for us

by Seam through injection  of the variables  labeled  by the annotations. Additionally,  we are already  in our business   object,  so there is no need to call anything  else except  maybe a database. Not only does the code  look cleaner  now, but we do not have to worry about the HttpRequest  and HttpSession   data explicitly;  it is handled behind the scenes  by Seam.

Requesting and Saving  Data

The previous example,  although   somewhat   trivial in problem solving,  hopefully  exposed you a bit to the power of using  Seam over traditional Struts applications.   In the following example,  we will still be using  our restaurant, but this time  we are going to save the

restaurants name. So you will first have to find the restaurant, and then the user can save it back to the page. This is drawn out for you in Figure  2-2.

Figure 2-2. Activity  diagram of a call to a page that wants  to save and validate  data

Just as before,  the user makes  a request  to the server  to find the best restaurant, which  is a retrieval process. Now the user can also input data and send it back to the server  to save a new restaurant. Listing 2-4 shows  the Struts version  of this code.

Listing 2-4. The Struts  Action for Retrieving  and Saving  the Best Restaurant

public class ChangeRestaurantStrutsAction        extends   Action     else



Notice  that I have introduced a Boolean  to decide  to save or update. We could  have

done this instead  with two separate method calls by using  DispatchAction.   However,  for those  not too familiar  with Struts, I did not want  to add to the codes complexity.  Also, this example  introduced DynaForm. The following  steps  indicate  what  the code  is doing:

1.  Cast the form to its instantiated type.

2.  Retrieve the Boolean  value to know whether  this is a save or update.

3.  If it is a save, perform the following:

a.  Retrieve the new best restaurant name that we are going to save.

b.  Retrieve the zip code  we are going to save it to.

c.  Save the new best restaurant based  on the preceding two parameters.

d.  Return to the completePage  mapping.

4.  If it is not a save, you request  the best restaurant for the zip code  by performing the following:

a.  Retrieve the best restaurant by using  the lookup  service.

b.  Save the best restaurant to the request  attribute as we did before.

So as you can see, this code  is a bit more  complex  than before,  but using  the form object  does save some  time  on more-complex    matters. Now lets take a look at the Seam example  in Listing 2-5.

Listing 2-5. The Seam  Component   for Retrieving  and Changing  the Best Restaurant



public class ChangeRestaurantAction     implements   IChangeRestaurantAction

public String saveBestRestaurant()       


As you can see in this example,  we only had to add another method to save the restaurant, and we had to simply  add another annotation to declare  that the restaurant variable  can be inputted as well. Quite  the minimal  modifications    for the performance increase.

Logging  In

So now that we have covered  two basic  examples  of retrieving and saving data,  we are going to go on to another common   type of code—for  logging in. Now there are lots of different ways to log in to a website  and many  authentication models  to use. In fact, Chapter  8 covers  some  Seam-specific   ways of logging in.

For this example,  however, we are going to stick to a very basic  authentication process: you attempt to log in with a username and password;   if you are verified,  your username will be saved  to the session.  The HttpSession   object  is a common   object  for saving login data because  it will persist  the entire  time  that you are active  on the site. When  you read  this, do not get too worked  up about this login model,  but look at it as a way of saving session-related    data.  Figure  2-3 shows  an activity  diagram of what  we are going to do.

This is a simple  one-request run—the  user  either  correctly  inputs the username and password and continues,   or is rejected  to a failure  page.  Listing 2-6 provides the Struts version  of this code.

Listing 2-6. The Struts  Page for Logging In to a Website

public class LoginStrutsAction      extends   Action     else



Figure 2-3. Activity  diagram of a call that is for logging in to a page

The biggest  difference  between this page and the pages  you have seen  before  is that now we are saving to the HttpSession   object.  Another  thing  to keep in mind when  using Struts or any HttpSession   object  directly  is that even if you retrieve an object  from the ses- sion, you cannot just change  the object  but you will have to reset  the attribute on the session  again.  The steps  that this page goes through are as follows:

1.  Retrieve the username.

2.  Retrieve the password.

3.  Call the business   service  to see whether  this is a valid login.

4.  If it is a valid login, save the username to the session  and return to the

success page.

5.  If you are not successful,  forward to a failed  page. Listing 2-7 provides the Seam version  of this page.

Listing 2-7. The Seam  Page for Logging In to a Website



public class LoginAction   implements   ILoginAction      else



Again, the majority  of this page should  seem  simple,  except all we have to do is label the variable  to describe  that the object  is exposed  to HttpSession.   You will notice  that this code  is clean,  and once  again  the amount of code  is less. Furthermore, we are even in the business   service  already!

Listing  and Viewing a Page

For our final example,  I am going to show  off one my favorite  features  with Seam: its ability  to display  lists and retrieve them. For this example,  we are going to access  a page with a list of restaurants. The user  then has the ability  to click on any of the restaurants and retrieve detailed  information about it. Figure  2-4 shows  the activity  diagram for

our request.

This type of request  is fairly standard with web operations.   Listing 2-8 shows  how we perform this with Struts.

Listing 2-8. The Struts  Action for Displaying  a List and Retrieving  a Specific Restaurant

public   class ListOfRestaurantStrutsAction          extends   Action   

return  mapping.findForward('success');



Figure 2-4. Activity  diagram showing  all the hooks  the user needs into the system

Part of the complexity  of this code  is actually  hidden from us right now because  we will have to have the business   service  object  retrieve the list. Also notice  how having  to retrieve the name of the restaurant can be wasteful  because  it requires  a second  call to the database. Finally, notice  that we would  have to keep retrieving the restaurants list each  time  we switch  between viewing one and the list page. This could  be resolved  by saving the list to HttpSession,   but that adds  many  more  problems because  you do not want  to keep objects  in the session  forever  and will have to determine when  to destroy the session.  The steps  for this operation   are as follows:

1.  Retrieve the restaurant ID.

2.  Retrieve the list of restaurants.

3.  Save the list of restaurants to a request  variable.

4.  If the restaurant ID is populated,   we want  to retrieve one particular restaurant.

a.  Retrieve the restaurant from the database, based  on the restaurant ID.

b.  Save the restaurant to the request.

Hopefully  you can see not only the waste  but the issues  that can arise if you want  to do anything  including   delete.  Even if you saved  the Restaurant   object  to the session  and wanted  to delete  it, you would  have to delete  from the database and the list. This can all get complicated   quickly,  but fortunately   Seam has a simplistic  approach that takes  care of all the plumbing   for us. You can see this in Listing 2-9.

Listing 2-9. The Seam  Component   for Displaying  a List and Retrieving  a Specific Restaurant



public   class ListOfRestaurantAction       implements  IListOfRestaurantAction       


Now at first glance  this page may seem  extremely  confusing.   After all, before  we were

defining  the returns, so the page knew where  to go. The multiple  returns are missing;  we are clearly doing  two calls as before,  yet only one method exists. To explain  briefly, we are using  annotations to define  our list; we then define  the selected  object  on the list, and finally a method to retrieve our list. Chapter  5 provides more  detail.  This method is where you can start to see the power of Seam.  In fact, unlike  the other examples  that clearly required   writing  some  database code  or logic, this is all the code  you would  need to write on the server,  assuming   that the Restaurant   object  is an EB.

Sample Applications

Whats a book without  examples?  Obviously,  we need applications   on which  to base  our code.  Many books  have one example  throughout the whole  text, and although   this can be a good method,   it can make  it overly complex  to understand the sample  code  when trying to do simple  things.  Also, Seam  provides a variety  of business   solutions,   so one sample  that incorporates    all of these  solutions   would  be extremely  complex.

Instead,  I took the approach of giving you a few examples  to base  your work on. I present examples  sporadically   throughout the book,  depending   on the problem needing to be solved.  Most of these  examples  have deployable   code  in the downloadable    source.

However,  I present three main  examples  that create  more-robust and solid applica- tions.  These  examples,  more  than others,  will be referenced   throughout the book in different parts depending   on what  we are doing.  I will not provide complete   details about each  of these  examples;  however, the downloadable    code  will have complete working  examples  of them. The sample  code  will include  everything   you need to run the code,  including   Ant build  scripts  and database build  scripts.  You can either  set up this code  ahead of time,  use the code  as you go along,  or wait until  you are done with the

book; the choice  is up to you.

Note Sample code can be downloaded from

Garage Sale

Garage  Sale is our basic  application   for CRUD-based   examples  (CRUD stands for create, read, update,  and delete). The Garage  Sale application   allows users  to add,  edit, search, list, and delete  garage  sales. Within  each  garage  sale is a list of items  that a user can view. The person  who created the garage  sale can add and delete  items  from the garage  sale. These  are all the basic  options  any normal CRUD application   gives you. Figure  2-5 pro- vides the database diagram for this application.

Figure 2-5. A database  diagram of our Garage Sale application

The database has just two tables:  one for the house  that is having  the sale, and the second  for all the items  they are selling. One house  can therefore have multiple  items  for sale. Figure  2-6 provides a use case diagram of this event.

As you can see, there are two sets of paths into the application.   A seller can go in, cre- ate a garage  sale, and add sale items  to it. The seller should  also be able to delete  an item after its sold or after making  a mistake.  The seller will be able to get a simple  list page of items  back for the sale. The potential   buyer  has but one option,  and that is to search  for garage  sales. After selecting  a garage  sale to view, the user can then see the items  of the garage  sale.


Figure 2-6. Use case diagram of the Garage Sale application

Travel Reservations

The Travel Reservations   application   is a slightly more-complex    system.  The goal of this system  is to allow booking  of flights, hotels,  and cars. This system  is wizard based  and has previous screen items  feeding  into the next screen.  This application   allows users  to create multiple  travel reservations   in different screens.  Each screen should  know its own path, but also should  be able to keep track of whats going on in different screens.  Figure  2-7 shows  the database diagram for the travel reservations   database.

The travel reservations   system  is a more  intermediate    system.  You have three base database lookup  tables:  Flight, Car, and Hotel. These  tables  should  be loaded  dynami- cally when  a user enters the page. The list of items  is generated on the fly for each  page, but on the page itself the items  will stay persisted   for as long as the user is on the page.

You will notice  that there are not many  mechanisms    to determine what  days are available  or a subtable   for different car types. The main  reason  for this is to keep the com- plexity down  and not worry about fillers.

The tables  above  the three base  tables  (FlightBooked,   CarBooked,  and HotelBooked) will keep track of the dates  booked  for the users trip. Finally, the Booking  table  is there to keep all the data stored  for one user.  Figure  2-8 shows  the user flow for this application.

Figure 2-7. Travel Reservations  database  diagram

Figure  2-8 shows  the user flow for this application.


Figure 2-8. User flow diagram for travel reservations

Despite  having  a more  complex  database than the Garage  Sale application,   the sys- tem is relatively  simple.  The user can select  airfare,  hotel,  and a car. The user can choose to work in order  or skip certain steps  and go to the end.  At the end,  on the purchase, the transaction is committed   to the database.

Ticketing  System

Our final example  application   is a ticketing  system.  This is the kind of ticketing  system that has multiple  users  requiring  input to the same  object.  Users  can interact  with the ticket,  and supervisors   need to approve different areas  of the system  that other users inputted. Figure  2-9 provides the database diagram for the ticketing  system.

Figure 2-9. Database  diagram of the ticketing  system

This database is simpler  in layout.  It is for a troubleshooting ticket  system.  There  is a name, description,   and severity.  You will also notice  the TicketOwner   table;  this is actually a temporal table.  The end date will be null for the entry that identifies  the current owner of the ticket. This allows you to keep track of who owned  the ticket  and when.  Figure  2-10 shows  the flow for this application.


Figure 2-10. Navigation   diagram for the ticketing  system

This navigation   diagram shows  that there are multiple  user interactions   with the ticketing  system.  Users  can access  the same  ticket  and perform operations   on the ticket within  the work flow rules  of the ticketing  system.  You will get to use this application   in Chapter  7.


The goal of this chapter was to introduce you to basic  web design  concepts.   These  con- cepts  were to make  you think  about the different problems you may encounter when creating  web pages.  I presented these  problems so you can learn how Seam  helps  sim- plify handling   the sometimes   complex  issues  frequently   encountered by web developers.

Even for those  who are experienced   developers,   this chapter should  have started to show you the ease that Seam  brings you in designing  web applications.   Of course,  you are going to have to wait a few more  chapters   before  diving into full Seam  development. I still need to go over the fundamentals    of JSF and EJB3 to prepare you to use Seam.

I also briefly discussed   the applications   we are going to create.  These  three applica- tions  form the backbone   of our examples  in later chapters.   These  examples  each represent different levels of complexity.  I will refer to these  in later chapters,   so you may want  to at least take note of the database diagrams  for them.

Politica de confidentialitate



Vizualizari: 641
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2022 . All rights reserved

Distribuie URL

Adauga cod HTML in site