Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-integrating-spring-framework-hibernate-orm-framework-part-1
Packt
31 Dec 2009
6 min read
Save for later

Integrating Spring Framework with Hibernate ORM Framework: Part 1

Packt
31 Dec 2009
6 min read
Spring is a general-purpose framework that plays different roles in many areas of application architecture. One of these areas is persistence. Spring does not provide its own persistence framework. Instead, it provides an abstraction layer over JDBC, and a variety of O/R mapping frameworks, such as iBATIS SQL Maps, Hibernate, JDO, Apache OJB, and Oracle TopLink. This abstraction allows consistent, manageable data-access implementation. Spring's abstraction layer abstracts the application from the connection factory, the transaction API, and the exception hierarchies used by the underlying persistence technology. Application code always uses the Spring API to work with connection factories, utilizes Spring strategies for transaction management, and involves Spring's generic exception hierarchy to handle underlying exceptions. Spring sits between the application classes and the O/R mapping tool, undertakes transactions, and manages connection objects. It translates the underlying persistence exceptions thrown by Hibernate to meaningful, unchecked exceptions of type DataAccessException. Moreover, Spring provides IoC and AOP, which can be used in the persistence layer. Spring undertakes Hibernate's transactions and provides a more powerful, comprehensive approach to transaction management. The Data Access Object pattern Although you can obtain a Session object and connect to Hibernate anywhere in the application, it's recommended that all interactions with Hibernate be done only through distinct classes. Regarding this, there is a JEE design pattern, called the DAO pattern. According to the DAO pattern, all persistent operations should be performed via specific classes, technically called DAO classes. These classes are used exclusively for communicating with the data tier. The purpose of this pattern is to separate persistence-related code from the application's business logic, which makes for more manageable and maintainable code, letting you change the persistence strategy flexibly, without changing the business rules or workflow logic. The DAO pattern states that we should define a DAO interface corresponding to each DAO class. This DAO interface outlines the structure of a DAO class, defines all of the persistence operations that the business layer needs, and (in Spring-based applications) allows us to apply IoC to decouple the business layer from the DAO class. Service Facade Pattern In implementation of data access tier, the Service Facade Pattern is always used in addition to the DAO pattern. This pattern indicates using an intermediate object, called service object, between all business tier objects and DAO objects. The service object assembles the DAO methods to be managed as a unit of work. Note that only one service class is created for all DAOs that are implemented in each use case. The service class uses instances of DAO interfaces to interact with them. These instances are instantiated from the concrete DAO classes by the IoC container at runtime. Therefore, the service object is unaware of the actual DAO implementation details. Regardless of the persistence strategy your application uses (even if it uses direct JDBC), applying the DAO and Service Facade patterns to decouple application tiers is highly recommended. Data tier implementation with Hibernate Let's now see how the discussed patterns are applied to the application that directly uses Hibernate. The following code shows a sample DAO interface: package com.packtpub.springhibernate.ch13;import java.util.Collection;public interface StudentDao { public Student getStudent(long id); public Collection getAllStudents(); public Collection getGraduatedStudents(); public Collection findStudents(String lastName); public void saveStudent(Student std); public void removeStudent(Student std);} The following code shows a DAO class that implements this DAO interface: package com.packtpub.springhibernate.ch13;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.HibernateException;import org.hibernate.Query;import java.util.Collection;public class HibernateStudentDao implements StudentDao { SessionFactory sessionFactory; public Student getStudent(long id) { Student student = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); student = (Student) session.get(Student.class, new Long(id)); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return student; } public Collection getAllStudents(){ Collection allStudents = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Query query = session.createQuery( "from Student std order by std.lastName, std.firstName"); allStudents = query.list(); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return allStudents; } public Collection getGraduatedStudents(){ Collection graduatedStudents = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Query query = session.createQuery( "from Student std where std.status=1"); graduatedStudents = query.list(); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return graduatedStudents; } public Collection findStudents(String lastName) { Collection students = null; Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); Query query = session.createQuery( "from Student std where std.lastName like ?"); query.setString(1, lastName + "%"); students = query.list(); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } return students; } public void saveStudent(Student std) { Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); session.saveOrUpdate(std); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } } public void removeStudent(Student std) { Session session = HibernateHelper.getSession(); Transaction tx = null; try { tx = session.beginTransaction(); session.delete(std); tx.commit(); tx = null; } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { session.close(); } } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; }} As you can see, all implemented methods do routines. All obtain a Session object at first, get a Transaction object, perform a persistence operation, commit the transaction, rollback the transaction if exception occurs, and finally close the Session object. Each method contains much boilerplate code that is very similar to the other methods. Although applying the DAO pattern to the persistence code leads to more manageable and maintainable code, the DAO classes still include much boilerplate code. Each DAO method must obtain a Session instance, start a transaction, perform the persistence operation, and commit the transaction. Additionally, each DAO method should include its own duplicated exception-handling implementation. These are exactly the problems that motivate us to use Spring with Hibernate. Template Pattern: To clean the code and provide more manageable code, Spring utilizes a pattern called Template Pattern. By this pattern, a template object wraps all of the boilerplate repetitive code. Then, this object delegates the persistence calls as a part of functionality in the template. In the Hibernate case, HibernateTemplate extracts all of the boilerplate code, such as obtaining a Session, performing transaction, and handing exceptions.
Read more
  • 0
  • 0
  • 4062

article-image-starting-tomcat-6-part-1
Packt
31 Dec 2009
9 min read
Save for later

Starting Up Tomcat 6: Part 1

Packt
31 Dec 2009
9 min read
Using scripts The Tomcat startup scripts are found within your project under the bin folder. Each script is available either as a Windows batch file (.bat), or as a Unix shell script (.sh). The behavior of either variant is very similar, and so I'll focus on their general structure and responsibilities, rather than on any operating system differences. However, it is to be noted that the Unix scripts are often more readable than the Windows batch files. In the following text, the specific extension has been omitted, and either .bat or .sh should be substituted as appropriate. Furthermore, while the Windows file separator '' has been used, it can be substituted with a '/' as appropriate. The overall structure of the scripts is as shown—you will most often invoke the startup script. Note that the shutdown script has a similar call structure. However, given its simplicity, it lends itself to fairly easy investigation, and so I leave it as an exercise for the reader. Both startup and shutdown are simple convenience wrappers for invoking the catalina script. For example, invoking startup.bat with no command line arguments calls catalina.bat with an argument of start. On the other hand, running shutdown.bat calls catalina.bat with a command line argument of stop. Any additional command line arguments that you pass to either of these scripts are passed right along to catalina.bat. The startup script has the following three main goals: If the CATALINA_HOME environment variable has not been set, it is set to the Tomcat installation's root folder. The Unix variant defers this action to the catalina script. It looks for the catalina script within the CATALINA_HOMEbin folder. The Unix variant looks for it in the same folder as the startup script. If the catalina script cannot be located, we cannot proceed, and the script aborts. It invokes the catalina script with the command line argument start followed by any other arguments supplied to the startup script. The catalina script is the actual workhorse in this process. Its tasks can be broadly grouped into two categories. First, it must ensure that all the environment variables needed for it to function have been set up correctly, and second it must execute the main class file with the appropriate options. Setting up the environment In this step, the catalina script sets the CATALINA_HOME, CATALINA_BASE, and CATALINA_TMPDIR environment variables, sets variables to point to various Java executables, and updates the CLASSPATH variable to limit the repositories scanned by the System class loader. It ensures that the CATALINA_HOME environment variable is set appropriately. This is necessary because catalina can be called independently of the startup script. Next, it calls the setenv script to give you a chance to set any installation-specific environment variables that affect the processing of this script. This includes variables that set the path of your JDK or JRE installation, any Java runtime options that need to be used, and so on. If CATALINA_BASE is set, then the CATALINA_BASEbinsetenv script is called. Else, the version under CATALINA_HOME is used. If the CATALINA_HOMEbinsetclasspath does not exist, processing aborts. Else, the BASEDIR environment variable is set to CATALINA_HOME and the setclasspath script is invoked. This script performs the following activities: It verifies that either a JDK or a JRE is available. If both the JAVA_HOME and JRE_HOME environment variables are not set, it aborts processing after warning the user. If we are running Tomcat in debug mode, that is, if '–debug' has been specified as a command line argument, it verifies that a JDK (and not just a JRE) is available. If the JAVA_ENDORSED_DIRS environment variable is not set, it is defaulted to BASEDIRendorsed. This variable is fed to the JVM as the value of the –Djava.endorsed.java.dirs system property. The CLASSPATH is then truncated to point at just JAVA_HOMElibtools.jar. This is a key aspect of the startup process, as it ensures that any CLASSPATH set in your environment is now overridden.Note that tools.jar contains the classes needed to compile and run Java programs, and to support tools such as Javadoc and native2ascii. For instance, the class com.sun.tools.javac.main.Main that is found in tools.jar represents the javac compiler. A Java program could dynamically create a Java class file and then compile it using an instance of this compiler class. Finally, variables are set to point to various Java executables, such as java, javaw (identical to java, but without an associated console window), jdb (the Java debugger), and javac (the Java compiler). These are referred to using the _RUNJAVA, _RUNJAVAW, _RUNJDB, and _RUNJAVAC environment variables respectively. The CLASSPATH is updated to also include CATALINA_HOMEbinbootstrap.jar, which contains the classes that are needed by Tomcat during the startup process. In particular, this includes the org.apache.catalina.startup.Bootstrap class. Note that including bootstrap.jar on the CLASSPATH also automatically includes commons-daemon.jar, tomcat-juli.jar, and tomcat-coyote.jar because the manifest file of bootstrap.jar lists these dependencies in its Class-Path attribute. If the JSSE_HOME environment variable is set, additional Java Secure Sockets Extension JARs are also appended to the CLASSPATH. Secure Sockets Layer (SSL) is a technology that allows clients and servers to communicate over a secured connection where all data transmissions are encrypted by the sender. SSL also allows clients and servers to determine whether the other party is indeed who they say they are, using certificates. The JSSE API allows Java programs to create and use SSL connections. Though this API began life as a standalone extension, the JSSE classes have been integrated into the JDK since Java 1.4. If the CATALINA_BASE variable is not set, it is defaulted to CATALINA_HOME. Similarly, if the Tomcat work directory location, CATALINA_TMPDIR is not specified, then it is set to CATALINA_BASEtemp. Finally, if the file CATALINA_BASEconflogging.properties exists, then additional logging related system properties are appended to the JAVA_OPTS environment variable. All the CLASSPATH machinations described above have effectively limited the repository locations monitored by the System class loader. This is the class loader responsible for finding classes located on the CLASSPATH. At this point, our execution environment has largely been validated and configured. The script notifies the user of the current execution configuration by writing out the paths for CATALINA_BASE, CATALINA_HOME, and the CATALINA_TMPDIR to the console. If we are starting up Tomcat in debug mode, then the JAVA_HOME variable is also written, else the JRE_HOME is emitted instead. These are the lines that we've grown accustomed to seeing when starting up Tomcat. C:tomcatTOMCAT_6_0_20outputbuildbin>startupUsing CATALINA_BASE: C:tomcatTOMCAT_6_0_20outputbuildUsing CATALINA_HOME: C:tomcatTOMCAT_6_0_20outputbuildUsing CATALINA_TMPDIR: C:tomcatTOMCAT_6_0_20outputbuildtempUsing JRE_HOME: C:javajdk1.6.0_14 With all this housekeeping done, the script is now ready to actually start the Tomcat instance. Executing the requested command This is where the actual action begins. This script can be invoked with the following commands: debug [-security], which is used to start Catalina in a debugger jpda start, which is used to start Catalina under a JPDA debugger run [-security], which is used to start Catalina in the current window start [-security], which starts Catalina in a separate window stop, which is used to stop Catalina version, which prints the version of Tomcat The use of a security manager, as determined by the optional –security argument, is out of scope for this article. The easiest way to understand this part of catalina.bat is to deconstruct the command line that is executed to start up the Tomcat instance. This command takes this general form (all in one line): _EXECJAVAJAVA_OPTSCATALINA_OPTSJPDA_OPTSDEBUG_OPTS-Djava.endorsed.dirs="JAVA_ENDORSED_DIRS"-classpath "CLASSPATH"-Djava.security.manager-Djava.security.policy=="SECURITY_POLICY_FILE"-Dcatalina.base="CATALINA_BASE"-Dcatalina.home="CATALINA_HOME"-Djava.io.tmpdir="CATALINA_TMPDIR"MAINCLASSCMD_LINE_ARGSACTION Where: _EXECJAVA is the executable that should be used to execute our main class. This defaults to the Java application launcher, _RUNJAVA. However, if debug was supplied as a command-line argument to the script, this is set to _RUNJDB instead. MAINCLASS is set to org.apache.catalina.startup.Bootstrap ACTION defaults to start, but is set to stop if the Tomcat instance is being stopped. CMD_LINE_ARGS are any arguments specified on the command line that follow the arguments that are consumed by catalina. SECURITY_POLICY_FILE defaults to CATALINA_BASEconfcatalina.policy. JAVA_OPTS and CATALINA_OPTS are used to carry arguments, such as maximum heap memory settings or system properties, which are intended for the Java launcher. The difference between the two is that CATALINA_OPTS is cleared out when catalina is invoked with the stop command. In addition, as indicated by its name, the latter is targeted primarily at options for running a Tomcat instance. JPDA_OPTS sets the Java Platform Debugger Architecture (JPDA) options to support remote debugging of this Tomcat instance. The default options are set in the script. It chooses TCP/IP as the protocol used to connect to the debugger (transport=dt_socket), marks this JVM as a server application (server=y), sets the host and port number on which the server should listen for remote debugging requests (address=8000), and requires the application to run until the application encounters a breakpoint (suspend=n). DEBUG_OPTS sets the -sourcepath flag when the Java Debugger is used to launch the Tomcat instance. The other variables are set as seen in the previous section. At this point, control passes to the main() method in Bootstrap.java. This is where the steps that are unique to script-based startup end. The rest of this article follows along with the logic coded into Bootstrap.java and Catalina.java.
Read more
  • 0
  • 0
  • 2805

article-image-creating-web-application-jboss-5
Packt
31 Dec 2009
7 min read
Save for later

Creating a Web Application on JBoss AS 5

Packt
31 Dec 2009
7 min read
Wonder what was the first message sent through Internet? At 22:30 hours on October 29, 1969, a message was transmitted using ARPANET (the predecessor of the global Internet) on a host-to-host connection. It was meant to transmit "login". However, it transmitted just "lo" and crashed. Developing web layout The basic component of any Java web application is the servlet. Born in the middle of the 90s, servlets quickly gained success against their competitors, the CGI scripts. This was because of some innovative features, especially the ability to execute requests concurrently, without the overhead of creating a new process for each request. However, a few things were missing, for example, the servlet API did not address any APIs specifically for creating the client GUI. This resulted in multiple ways of creating the presentation tier, generally with tag libraries that differed from job to job and from individual developers. The second thing that was missing in the servlet specification was a clear distinction between the presentation tier and the backend. A plethora of web frameworks tried to fill this gap; particularly the Struts framework effectively realized a clean separation of the model (application logic that interacts with a database) from the view (HTML pages presented to the client) and the controller (instance that passes information between view and model). However, the limitation of these frameworks was that even if they realized a complete modular abstraction, they still failed as they always exposed theHttpServletRequest and HttpServletSessionobjects to their action(s). Their actions, in turn, needed to accept the interface contracts such as ActionForm, ActionMapping, and so on. The JavaServer Faces that emerged on the stage a few years later pursued a different approach. Unlike request-driven Model–View–Controller (MVC) web frameworks, JSF chose a component-based approach that ties the user interface component to a well-defined request processing lifecycle. This greatly simplifies the development of web applications. The JSF specification allows you to have presentation components be POJOs. This creates a cleaner separation from the servlet layer and makes it easier to do testing by not requiring the POJOs to be dependent on the servlet classes. In the following sections, we will describe how to create a web layout for our application store using the JSF technology. For an exhaustive explanation of the JSF framework, we suggest you to surf the JSF homepage at http://java.sun.com/javaee/javaserverfaces/. Installing JSF on JBoss AS JBoss AS already ships with the JSF libraries, so the good news is that you don't need to download or install them in the application server. There are different implementations of the JSF libraries. Earlier JBoss releases adopted the Apache MyFaces library. JBoss AS 4.2 and 5.x ship with the Common Development and Distribution License (CDDL) implementation (now called "Project Mojarra") of the JSF 1.2 specification that is available from the java.net open source community. Switching to another JSF implementation is anyway possible. All you have to do is package your JSF libraries with your web application and configure your web.xml to ignore the JBoss built-in implementation: <context-param><param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name><param-value>true</param-value></context-param> We will start by creating a new JSF project. From the File menu, select New | Other | JBoss Tools Web | JSF | JSF Web project. The JSF applet wizard will display, requesting the Project Name, the JSF Environment, and the default starting Template. Choose AppStoreWeb as the project name, and check that the JSF Environment used is JSF 1.2. You can leave all other options to the defaults and click Finish. Eclipse will now suggest that you switch to the Web Projects view that logically assembles all JSF components. (It seems that the current release of the plugin doesn't understand your choice, so you have to manually click on the Web Projects tab.) The key configuration file of a JSF application is faces-config.xml contained in the Configuration folder. Here you declare all navigation rules of the application and the JSF managed beans. Managed beans are simple POJOs that provide the logic for initializing and controlling JSF components, and for managing data across page requests, user sessions, or the application as a whole. Adding JSF functionalities also requires adding some information to your web.xml file so that all requests ending with a certain suffix are intercepted by the Faces Servlet. Let's have a look at the web.xml configuration file: <?xml version="1.0"?><web-app version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><display-name>AppStoreWeb</display-name><context-param><param-name>javax.faces.STATE_SAVING_METHOD</param-name><param-value>server</param-value></context-param><context-param> [1]<param-name>com.sun.faces.enableRestoreView11Compatibility</param-name><param-value>true</param-value></context-param><listener><listener-class>com.sun.faces.config.ConfigureListener</listener-class></listener><!-- Faces Servlet --><servlet><servlet-name>Faces Servlet</servlet-name><servlet-class>javax.faces.webapp.FacesServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><!-- Faces Servlet Mapping --><servlet-mapping><servlet-name>Faces Servlet</servlet-name><url-pattern>*.jsf</url-pattern></servlet-mapping><login-config><auth-method>BASIC</auth-method></login-config></web-app> The context-param pointed out here [1] is not added by default when you create a JSF application. However, it needs to be added, else you'll stumble into an annoying ViewExpiredException when your session expires (JSF 1.2). Setting up navigation rules In the first step, we will define the navigation rules for our AppStore. A minimalist approach would require a homepage that displays the orders, along with two additional pages for inserting new customers and new orders respectively. Let's add the following navigation rule to the faces-config.xml: <faces-config><navigation-rule><from-view-id>/home.jsp</from-view-id> [1]<navigation-case><from-outcome>newCustomer</from-outcome> [2]<to-view-id>/newCustomer.jsp</to-view-id></navigation-case><navigation-case><from-outcome>newOrder</from-outcome> [3]<to-view-id>/newOrder.jsp</to-view-id></navigation-case></navigation-rule><navigation-rule><from-view-id></from-view-id> [4]<navigation-case><from-outcome>home</from-outcome><to-view-id>/home.jsp</to-view-id></navigation-case></navigation-rule></faces-config> In a navigation rule, you can have one from-view-id that is the (optional) starting page, and one or more landing pages that are tagged as to-view-id. The from-outcome determines the navigation flow. Think about this parameter as a Struts forward, that is, instead of embedding the landing page in the JSP/servlet, you'll simply declare a virtual path in your JSF beans. Therefore, our starting page will be home.jsp [1] that has two possible links—the newCustomer.jsp form [2] and the newOrder.jsp form [3]. At the bottom, there is a navigation rule that is valid across all pages [4]. Every page requesting the home outcome will be redirected to the homepage of the application. The above JSP will be created in a minute, so don't worry if Eclipse validator complains about the missing pages. This configuration can also be examined from the Diagram tab of your faces-config.xml: The next piece of code that we will add to the confi guration is the JSF managed bean declaration. You need to declare each bean here that will be referenced by JSF pages. Add the following code snippet at the top of your faces-config.xml (just before navigation rules): <managed-bean><managed-bean-name>manager</managed-bean-name> [1]<managed-bean-class>com.packpub.web.StoreManagerJSFBean</managed-bean-class> [2]<managed-bean-scope>request</managed-bean-scope> [3]</managed-bean> The <managed-bean-name> [1] element will be used by your JSF page to reference your beans. The <managed-bean-class> [2] is obviously the corresponding class. The managed beans can then be stored within the request, session, or application scopes, depending on the value of the <managed-bean-scope> element [3].
Read more
  • 0
  • 0
  • 2729

article-image-starting-tomcat-6-part-2
Packt
31 Dec 2009
8 min read
Save for later

Starting Up Tomcat 6: Part 2

Packt
31 Dec 2009
8 min read
Bootstrapping the embedded container As we saw earlier, Bootstrap is simply a convenience class that is used to run the Embedded class, or rather to run Catalina, which subclasses Embedded. The Catalina class is intended to add the ability to process a server.xml file to its parent class. It even exposes a main() method, so you can invoke it directly with appropriate command-line arguments. Bootstrap uses its newly constructed serverLoader to load the Catalina class, which is then instantiated. It delegates the loading process to this Catalina instance's load() method. This method updates the catalina.base and catalina.home system properties to absolute references, verifies that the working directory is set appropriately, and initializes the naming system, which is Tomcat's implementation of the JNDI API. For now, all we need to note is that it indicates that JNDI is enabled by setting the catalina.useNaming system property to true, and prefixing the Context.URL_PKG_PREFIXES system property with the package org.apache.naming using a colon delimiter. The Context.URL_PKG_PREFIXES property indicates a list of fully qualified package prefixes for URL context factories. Setting org.apache.naming as the first entry makes it the first URL context factory implementation that will be located. For the java:comp/env Environment Naming Context (ENC), the actual class name for the URL context factory implementation is generated as org.apache.naming.java.javaURLContextFactory. If the Context.INITIAL_CONTEXT_FACTORY is currently not set for this environment, then this is set as the default INITIAL_CONTEXT_FACTORY to be used. Bootstrapping the Tomcat component hierarchy The configuration for a Tomcat instance is found in the confserver.xml file. This file is now processed, converting each element found into a Java object. The net result at the end of this processing is a Java object tree that mirrors this configuration file. This conversion process is facilitated by the use of the Apache Commons Digester project (http://commons.apache.org/digester/), an open source Commons project that allows you to harness the power of a SAX parser while at the same time avoiding the complexity that comes with event driven parsing. Commons Digester The Digester project was originally devised as a way of unmarshalling the struts-config.xml configuration file for Struts, but was moved out to a Commons project due to its general purpose usefulness. The basic principle behind the Digester is very simple. It takes an XML document and a RuleSet document as inputs, and generates a graph of Java objects that represents the structure that is defined in the XML instance document. There are three key concepts that come into play when using the Digester—a pattern, a rule, and an object stack. The pattern As the digester parses the input XML instance document, it keeps track of the elements it visits. Each element is identified by its parent's name followed by a forward slash ('/') and then by its name. For instance, in the example document below, the root element is represented by the pattern rolodex. Two <contact> elements are represented by the pattern rolodex/contact, the <company> elements are represented by the pattern rolodex/contact/company, and so on. <rolodex type=paperSales><contact id="1"><firstname>Damodar</firstname><lastname>Chetty</lastname><company>Software Engineering Solutions, Inc.</company></contact><contact id="2"><firstname>John</firstname><lastname>Smith</lastname><company>Ingenuitix, Inc.</company></contact></rolodex> The rule A rule specifies the action(s) that the Digester should take when a particular pattern is encountered. The common rules you will encounter are: Creational actions (create an instance of a given class to represent this XML element) Property setting actions (call setters on the Java object representing this XML element, passing in the value of either a child element or an attribute) Method invocation actions (call the specified method on the Java object representing this element, passing in the specified parameters) Object linking actions (set an object reference by calling a setter on one object while passing in the other as an argument) The object stack As objects are created, using the creational actions discussed above, Digester pushes them to the top of its internal stack. All actions typically affect the object at the top of the stack. A creational action will automatically pop the element on the top of the stack when the end tag for the pattern is detected. Using the Digester The typical sequence of actions is to create an object using a creational action, set its properties using a property setting action, and once the object is fully formed, to pop it off the top of the stack by linking it to its parent, which is usually just below it on the stack. Once the child has been popped off, the parent is once again at the top of the stack. This repeats as additional children objects are created, initialized, linked, and popped. Once all the children are processed and the parent object is fully initialized, the parent itself is popped off the stack, and we are done. You instantiate an org.apache.commons.digester.Digester by invoking the createDigester() method of org.apache.commons.digester.xmlrules.DigesterLoader and passing it the URL for the file containing the patterns and rules. Patterns and rules can also be specified programmatically by calling methods directly on the digester instance. However, defining them in a separate XML RuleSet instance document is much more modular, as it extracts rule configuration out of program code, making the code more readable and maintainable. Then, you invoke the parse() method of a Digester instance and pass it the actual XML instance document. The digester uses its configured rules to convert elements in the instance document into Java objects. The server.xml Digester The Catalina instance creates a Digester to process the server.xml file. Every element in this file is converted into an instance of the appropriate class, its properties are set based on configuration information in this file, and connections between the objects are set up, until what you are left with is a functioning framework of classes. This ability to configure the structure of cooperating classes using a declarative approach makes it easy to customize a Tomcat installation with very little effort. The createStartDigester() method in Catalina does the work of instantiating a new Digester and registering patterns and rules with it. The Catalina instance is then pushed to the top of the Digester stack, making it the root ancestor for all the elements parsed from the server.xml document. The rules can be described as follows: Pattern Rule Server Creational action: Instantiates an org.apache.catalina.core.StandardServer Set properties action: Copies attribute values over to the topmost object of the stack using mutator methods that are named similarly to the attribute Object linking action: Invokes setServer()to set this newly minted Server instance on the Catalina instance found on the stack. Server/ GlobalNamingResources Creational action: Instantiate an org.apache.catalina.deploy.NamingResources Set properties action: Copies attribute values from this element over to the topmost object on the stack Object linking action: Sets this newly instantiated object on the StandardServer instance at the top of the stack, by invoking its setGlobalNamingResources(). Server/Listener Creational action: Instantiate the class specified by the fully qualified class name provided as an attribute. Set properties action: Copy attributes from this element. Object linking action: Sets this instance on the StandardServer instance at the top of the stack, by invoking its addLifecycleListener() method with this new instance. Server/Service Creational action: Instantiates an org.apache.catalina.core.StandardService. Set properties action: Copy attributes from this element Object linking action: Invokes addService()on the StandardServer instance at the top of the stack passing in this newly minted instance Server/Service/Listener Creational action: Instantiate the class specified by the fully qualified class name provided as the className attribute Set properties action: Copy attributes from this element Object linking action: Invokes addLifecycleListener() on the StandardService instance at the top of the stack, passing in this listener instance Server/Service/Executor   Creational action: Instantiate the class org.apache.catalina.core.StandardThreadExecutor Set properties action: Copy attributes for this element Object linking action: Invokes addExecutor() with this instance, on the StandardService instance at the top of the stack Server/Service/Connector   Creational action: Instantiate the class org.apache.catalina.startup.ConnectorCreateRule Set properties action: Copy all attributes for this element except for the executor property Object linking action: Invokes addConnector(), passing in this instance, on the StandardService instance at the top of the stack Server/Service/Connector/Listener   Creational action: Instantiate the class specified by the fully qualified class name provided as the className attribute Set properties action: Copy attributes from this element Object linking action: Invokes addLifecycleListener(), passing in this instance, on the Connector instance at the top of the stack Server/Service/Engine   Set the Engine instance's parent class loader to the serverLoader
Read more
  • 0
  • 0
  • 1531

article-image-configuring-jms-resources-glassfish-part-2
Packt
31 Dec 2009
8 min read
Save for later

Configuring JMS Resources in GlassFish: Part 2

Packt
31 Dec 2009
8 min read
Configuring Open MQ using standalone tools Open MQ is shipped with a collection of utilities that can be used to configure and administer its runtime environment and resources. In this section, we provide a brief introduction to these utilities. For a detailed description of these utilities, you can refer to the Open MQ document set, located at http://docs.sun.com/app/docs/coll/1307.6. Starting and stopping the Open MQ broker The imqbrokerd utility is used to start a message broker. To start the default broker configured for GlassFish, open a command-line terminal, and enter the following commands: # cd $AS_INSTALL/imq/bin# ./imqbrokerd -tty You should see an output describing the information about the broker, and the confirmation of the successful start of the broker. If we do not specify a broker name, the imqbrokerd command will try to start the default broker named imqbroker. We can also supply a name <broker_name>. If the broker named <brokername> is already created, then the imqbrokerd command starts it; otherwise, a new broker of this name is created and then started. To shutdown the message broker, enter Ctrl+C in the terminal where imqbrokerd is running. Refer to the Open MQ documentation for information on how to run Open MQ brokers as a service. Administering the Open MQ Broker using imqcmd The main CLI utility we use to manage the Open MQ is imqcmd. It supports a long list of commands that can be used to create, destroy, modify, and display the information of a resource, such as a broker or a physical destination, and so on. To show the commands and options supported, enter the following commands in a terminal: # cd $AS_INSTALL/imq/bin# ./imqcmd -h As the first example, we can use the following command to display the status information of the currently running broker: # cd $AS_INSTALL/imq/bin# ./imqcmd query bkr -u admin Once you are prompted to enter the password, enter the default password admin. You should see an output describing the information regarding the currently running broker. We can store the password in a password file and use the -passfile option to point to this file. As another example, the following command queries the physical queue destination named PSQueueDest, and displays its information in the command-line terminal. # cd $AS_INSTALL/imq/bin# ./imqcmd query dst -t q -n PSQueueDest -u admin In this example, the option –t specifies the type of the destination as a topic, and the option –n PSQueueDest specifies the name of the physical destination. Refer to the help information and the MQ Administration Guide for a detailed description of the imqcmd utility. Using the imqadmin administration console The imqadmin utility is the primary GUI-based administration console of the Open MQ. It supports more of the functions of the imqcmd utility. Besides, it can also manage and confi gure the administration objects used by applications, such as specifying a naming service provider, and registering connection factories and destination resources in the naming service. To start the administration console, open a command-line terminal, and type the following command: # cd $AS_INSTALL/imq/bin# ./imqadmin You should see the administrator console window displayed. The administration console's navigation pane contains two top-level nodes, Brokers and Object Stores. The Brokers node organizes all the registered Open MQ brokers being managed by the administration console. The Object Stores node organizes the naming service providers to which the JMS administration objects (connection factories and destination resources) are registered. The following steps walk you through the typical process of adding a broker, and managing the broker resources. From the navigation pane of the administrator console, right click the Brokers node, and choose Add Broker. You should see a dialog box displayed. Fill out the Add Broker dialog according to the following screenshot, enter admin in the password field, and click OK. Now you should see the broker PSBroker is listed under the Brokers node with a red X on its icon, which indicates that the broker is not currently connected to the administrator console yet. Adding a broker does not create or start a new physical broker. It merely registers an existing broker to the administration console, and once we connect the administration console, we will be able to manage the resources of the broker. From the navigation pane, right click PSBroker under the Brokers node, and choose Connect to Broker. Once you connect to the broker, you should see the red X disappeared on the Brokers node. From the navigation pane, click Services under PSBroker. In the result pane, you should see all the available connection services listed for the broker, as shown in the following screenshot. From the navigation pane, right click Destinations under PSBroker, and select Add Broker Destination. You should see a dialog displayed. Enter PSQueueDest in the Destination Name field, select Queue radio button if not already selected. Keep all the other settings unchanged, and click OK to add the physical destination. From the navigation pane, click Destinations under PSBroker, the newly added PSQueueDest should appear. With physical destinations created, we can go through the following steps to configure the connection factory and destination resources in the Object Stores: Right click the Object Stores node in the navigation pane, and choose Add Object Store. Enter the following information in the dialog, and click OK to add the Object Store. Enter PSStore in the Object Store Label field. From the Name pull-down menu, select java.naming.factory.initial, and enter com.sun.jndi.fscontext.RefFSContextFactory in the value field. Click the Add button. These steps set the JNDI service provider you will use, to a filesystem based object store. From the Name pull-down menu, select java.naming.provider.url, and enter file:///tmp in the value field. Click the Add button. These steps set the exact location of the object store to the directory /tmp. In the navigation pane, you will see the object store PSStore you just added is listed under the Object Stores node with a red X on its icon, which indicates that the object store is not currently connected to the administrator console yet. From the navigation pane, right click PSStore under the Object Stores node, and choose Connect to Object Store. Once you connect to the object store, you should see that the red X has disappeared on the Object Stores node. From the navigation pane of the Open MQ administrator console, right click Destinations under PSStore node, and select Add Destination Object. You should see a dialog box displayed. Enter PSQueue in the Lookup Name field, select Queue from the Destination Type radio button. Enter PSQueueDest in the Destination Name field, and click OK to add the queue destination, as shown in the following screenshot. Now that we have seen how Open MQ is integrated with GlassFish, let's look at another very popular open source JMS implementation, ActiveMQ. Configuring ActiveMQ for GlassFish ActiveMQ is a very popular open source provider that is fully JMS 1.1 compliant. Besides, Active MQ has several very appealing features, such as cross language support for client development, high availability support, and support for REST API, and so on. For a more detailed description of the ActiveMQ product, visit the ActiveMQ project website hosted by Apache: http://activemq.apache.org. GlassFish is shipped with a generic JMS JCA resource adapter. In this section, we use ActiveMQ as an example to demonstrate how this generic resource adapter allows GlassFish to integrate with third-party JMS providers. Many JMS providers, including ActiveMQ includes its own JCA resource adapters for integrating with a Java EE application server. In this book, we do not cover this topic. You can refer to the JMS provider's documentation to enable this. For example, integrating ActiveMQ into GlassFish using ActiveMQ's resource adapter is actually quite similar to using the GlassFish resource adapter. Installing and configuring ActiveMQ The first step of integrating with ActiveMQ is to install it. Installing ActiveMQ is very straight forward. Simply download the latest ActiveMQ binary distribution (ZIP format for Window, and GZIP for UNIX/Linux/Mac OS X) from http://activemq.apache.org, and extract it to a target directory. For example, /opt. Next, let's start the ActiveMQ broker with the following commands: # cd /opt/apache-activemq-5.3.0/bin# ./activemq-admin start There are a variety of ways to configure ActiveMQ. The most comprehensive mechanism is to work with XML-based configuration files. This approach can be used to define all aspects of a message broker and its components, such as message destination. For a detailed discussion, please refer to the ActiveMQ documentation for more information on this. ActiveMQ also provides a simple web-based user interface for basic administrative tasks, such as creating/deleting message destinations (both topics and queues), sending messages to a destination for testing, and browsing messages in a destination, and so on. Now let's use the administrative user interface to configure a queue. To do this, complete the following steps: Open a browser, and access the ActiveMQ admin URL http://localhost:8161/admin. The ActiveMQ administration page appears. Click Queues. The browser lists the message queues configured for the ActiveMQ broker. By default, a queue named example.A is configured, as shown in the following screenshot. In the next section, we show you how to integrate this sample queue into GlassFish.  
Read more
  • 0
  • 0
  • 4746

article-image-including-google-maps-your-posts-using-apache-roller-40
Packt
31 Dec 2009
5 min read
Save for later

Including Google Maps in your Posts Using Apache Roller 4.0

Packt
31 Dec 2009
5 min read
Google Maps, YouTube, and SlideShare There are a lot of Internet and web services which you can use along with your blog to make your content more interesting for your viewers. With a good digital camera and video production software, you can make your own videos and presentations quickly and easily, and embed them in your posts with just a few clicks! For example, with Google Maps, you can add photos of your business to a custom map, and post it in your blog to attract customers. There are a lot of possibilities, and it all depends on your creativity! Including Google Maps in your posts Using Google Maps in your blog is a good way of promoting your business because you can show your visitors your exact location. Or you can blog about your favorite places and show them as if you were there, using your own photos. Time for action – using Google Maps There are a lot of things you can do with Google Maps, one of them is including maps of your favorite places in your blog, as we'll see in a moment: Open your web browser and go to Google Maps (http://maps.google.com). Type Eiffel Tower in the search textbox, and click on the Search Maps button or press Enter. Your web browser window will split in two areas, as shown in the following screenshot: Click on the Eiffel Tower link at the bottom-left part of the screen to see the Eiffel Tower's exact position in the map at the right panel:  Now click on the Satellite button to see a satellite image of the Eiffel Tower:      Drag the Eiffel Tower upwards using your mouse, to center it on the map area: Click on the Zoom here link inside the Eiffel Tower caption to see a closer image: If you look closely at the previous screenshot, you'll notice three links above the map: Print, Send, and Link. Click on Link to open a small window: Right-click on the Paste HTML to embed in website field to select the HTML code, and then click on the Copy option from the pop-up menu: Open a new web browser window and log into your Roller weblog. In the New Entry page, type The Eiffel Tower inside the Title field, and Eiffel Tower Google Maps inside the Tags field. Then click on the Toggle HTML Source button in the Rich Text editor toolbar, type This is an Eiffel Tower satellite image, courtesy of Google Maps:<br> inside the Content Field, press Enter, and paste the code you copied from the Google Maps web page: Scroll down the New Entry page and click on the Post to Weblog button. Then click on the Permalink field's URL, to see your Google Maps image posted in your blog. Click on the Zoom here link once to see a close-up of the Eiffel Tower, as shown in the following screenshot: What just happened? Now you can add Google Maps functionality inside your blog! Isn't that great? You just need to copy and paste the HTML code that the Google Maps produce automatically for you. If you want a bigger or smaller map, you can click on the Customize and preview embedded map link to customize the HTML code that you're going to paste into your blog: Then you just copy the HTML code produced by Google Maps and paste it into your blog post: If you have a Google Maps account, you can create customized maps and show them to your visitors, add photos and videos of places you've visited, and even write reviews about your favorite restaurants and hotels. Have a go hero – explore Google Maps Now that you've seen how to embed Google Maps in your weblog, it would be a great idea to create your own Google Maps account, and start exploring all the things that you can do—inserting photos and videos about places you've visited in your own custom maps, adding reviews of restaurants and other businesses in your locality, and so on. You can explore other users' maps, too. Once you get the hang of it, you'll be traveling around the world and meeting new people from your own PC. Including YouTube videos in your posts YouTube is one of the most popular video sharing websites in the world. You can include your favorite videos in your blog, or make your own videos and show them to your visitors. However, before you start complaining that we have already seen how to insert videos on your weblog, let me tell you that the big difference between uploading a video to your own blog server and uploading a video to a YouTube server is bandwidth. When someone plays back a video from your weblog, the blog server transfers the video data to your visitor's web browser, so that he/she can begin to see it, even before the video downloads completely. This is known as video streaming. Now, imagine you have 1,000 visitors, and each one of them is viewing the same video from your weblog! There would be a big amount of data flowing from your weblog to each visitor's web browser! That amount of data flowing from one PC to another is called bandwidth. You would need a very broad connection to be capable of transmitting your video to all those visitors. That's where YouTube comes into play. They have lots of bandwidth available for you and the other millions of users who share videos daily! So, if you plan to include a lot of videos in your weblog, it would be a great idea to get a YouTube account and start uploading them. In the following exercise, I'll show you how to include a YouTube video in your post, without having to upload it to your weblog.
Read more
  • 0
  • 0
  • 6090
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-installing-openvpn-linux-and-unix-systems-part-1
Packt
31 Dec 2009
10 min read
Save for later

Installing OpenVPN on Linux and Unix Systems: Part 1

Packt
31 Dec 2009
10 min read
Prerequisites All Linux/Unix systems must meet the following requirements to install OpenVPN successfully: Your system must provide support for the Universal TUN/TAP driver. The kernels newer than version 2.4 of almost all modern Linux distributions provide support for TUN/TAP devices. Only if you are using an old distribution or if you have built your own kernel, will you have to add this support to your configuration. This project's web site can be found at http://vtun.sourceforge.net/tun/. OpenSSL libraries have to be installed on your system. I have never encountered any modern Linux/Unix system that does not meet this requirement. However, if you want to compile OpenVPN from source code, the SSL development package may be necessary. The web site is http://www.openssl.org/. The Lempel-Ziv-Oberhumer (LZO) Compression library has to be installed. Again, most modern Linux/Unix systems provide these packages, so there shouldn't be any problem. LZO is a real-time compression library that is used by OpenVPN to compress data before sending. Packages can be found on http://openvpn.net/download.html, and the web site of this project is http://www.oberhumer.com/opensource/lzo/. Most Linux/Unix systems' installation tools are able to resolve these so-called dependencies on their own, but it might be helpful to know where to get the required software. Most commercial Linux systems, like SuSE, provide installation tools, like Yet another Setup Tool (YaST), and contain up-to-date versions of OpenVPN on their installation media (CD or DVD). Furthermore, systems based on RPM software can also install and manage OpenVPN software at the command line. Linux systems, like Debian, use sophisticated package management tools that can install software that is provided by repositories on web servers. No local media is needed, the package management will resolve potential dependencies by itself, and install the newest and safest possible version of OpenVPN. FreeBSD and other BSD-style systems use their package management tools such as pkg_add or the ports system. Like all open source projects, OpenVPN source code is available for download. These compressed tar.gz or tar.bz2 archives can be downloaded from http://openvpn.net/download.html and unpacked to a local directory. This source code has to be configured and translated (compiled) for your operating system. You can also install unstable, developer, or older versions of OpenVPN from http://openvpn.net/download.html. This may be interesting if you want to test new features of forthcoming versions. Daily (unstable!) OpenVPN source code extracts can be obtained from http://sourceforge.net/cvs/?group_id=48978. Here you find the Concurrent Versions System (CVS) repository, where all OpenVPN developers post their changes to the project files. Installing OpenVPN on SuSE Linux Installing OpenVPN on SuSE Linux is almost as easy as installing under Windows or Mac OS X. Linux users may consider it even easier. On SuSE Linux almost all administrative tasks can be carried out using the administration interface YaST. OpenVPN can be installed completely using this. The people distributing SuSE have always tried to include up-to-date software in their distribution. Thus, the installation media of OpenSuSE 11 already contains version 2.0.9 of OpenVPN, and both the Enterprise editions SLES 10 and the forthcoming SLES 11 that offer five years of support. Updates include up-to-date versions of OpenVPN. Both OpenSuSE and SLES use YaST for installing software. Using YaST to install software Start YaST. Under both GNOME and the K Desktop Environment (KDE—the standard desktop under SuSE Linux), you will find YaST in the main menu under System | YaST, or as an icon on the Desktop. If you are logged in as a normal user, you will be prompted to enter your root password and confirm the same. The YaST control center is started. This administration interface consists of many different modules, which are represented by symbols in the right half of the window and grouped by the labels on the left. After starting YaST, click on the symbol labeled Software Management in the right column to start the software management interface of YaST. The software management tool in YaST is very powerful. Under SuSE, data about the installed and installable software is kept in a database, which can be searched very easily. Select the entry Search in the drop-down list Filter: and enter openvpn in the Search field. YaST will find at least one entry that matches your search value openvpn. Depending on the (online) installation sources that you have configured, various add-ons and tools for OpenVPN will be found. If you chose to add the community repositories like I did on this system, then OpenSuSE will list more than 10 hits. Select the entry openvpn by checking the box besides the entry in the first column. If you want to obtain information about the OpenVPN package, have a look at the lower half of the right side—here you will find the software Description, Technical Data, Dependencies, and more information about the package that you have selected. Click on the Accept button to start the OpenVPN installation. If you installed from a local medium, then put your CD or DVD in your local drive now. YaST will retrieve the OpenVPN files from your installation media. If you have configured your system to use one of the web/FTP servers of SuSE for installation, then this might take a while. The files are unpacked and installed on your system, and YaST updates the configuration. This is managed by the script SuSEconfig and other scripts that are called by it. SuSEconfig and YaST were once very infamous for deleting local configuration created by the local administrator or omitting relevant changes. This problem only occurred when updating and re-installing software that was previously installed. However, the latest SuSE versions have proven very reliable, and the system configuration tools never delete configuration files that you have added manually. Instead, the standard configuration files installed with the new software package may be renamed to <file>.rpmnew or similar, and your configuration is loaded. During installation, SuSEconfig calls several helper scripts and updates your configuration, and informs you of the progress in a separate window. After successful software installation, you are prompted if you want to install more packages or exit the installation. Click on the Finish button. The Novell/OpenSuSE teams have added a very handy tool called zypper to their package management. From version 10.1 onwards, you can simply install software from a root console by typing zypper in openvpn. Of course this only works if you know the exact name of the package that you want to install. If not, then you will have to search for it, for example, by using zypper search vpn. Installing OpenVPN on Red Hat Fedora using yum If you are using Red Hat Fedora, the Yellow dog Updater, Modified (yum) is probably the easiest way to install software. It can be found on http://linux.duke.edu/projects/yum/, and provides many interesting features, such as automatic updates, solving dependency problems, and managing installation of software packages. Even though OpenVPN installation on Fedora can only be done on the command line, it still is a very easy task. The installation makes use of the commands wget, rpm, and yum. wget: A command-line download manager suitable for ftp or http downloads. rpm: The Red Hat Package Manager is a software management system used by distributions like SuSE or Red Hat. It keeps track of changes and can solve dependencies between programs. yum: This provides a simple installation program for RPM-based software. To use yum, you have to adapt its configuration file as follows: Log in as administrator (root). Change to Fedora's configuration directory /etc. Save the old, probably original, configurations file yum.conf by renaming or moving it. You can use commands such as mv yum.conf yum.conf_fedora_org to accomplish this. The web site http://www.fedorafaq.org/ provides a suitable configuration file for yum. Download the file http://www.fedorafaq.org/samples/yum.conf using wget. The command-line syntax is: wget http://www.fedorafaq.org/samples/yum.conf At the same web site a sophisticated yum configuration is available for downloading. Install this as well: rpm -Uvh http://www.fedorafaq.org/yum The following excerpt shows the output of these five steps on the system: [root@fedora ~]# cd /etc [root@fedora etc]# mv yum.conf yum.conf.org [root@fedora etc]# wget http://www.fedorafaq.org/samples/yum.conf --11:33:25-- http://www.fedorafaq.org/samples/yum.conf => `yum.conf' Resolving www.fedorafaq.org... 70.84.209.18 Connecting to www.fedorafaq.org[70.84.209.18]:80... connected. HTTP request sent, awaiting response... 200 OK Length: 595 [text/plain] 100%[========================================================== ================================================>] 595 --.- -K/s 11:33:25 (405.20 KB/s) - `yum.conf' saved [595/595] [root@fedora etc]# rpm -Uvh http://www.fedorafaq.org/yum Retrieving http://www.fedorafaq.org/yum Preparing... ######################################### ## [100%] 1:yum-fedorafaq ######################################### ## [100%] [root@fedora etc]# The rest of the OpenVPN installation is very simple. Just enter yum install openvpn in your root shell. Now yum will start and give you a lot of output. We will have a short look at the things yum does. [root@fedora ~]#yum install openvpn Setting up Install Process Setting up repositories livna 100% |=========================| 951 B 00:00 updates-released 100% |=========================| 951 B 00:00 base 100% |=========================| 1.1 kB 00:00 extras 100% |=========================| 1.1 kB 00:00 Reading repository metadata in from local files primary.xml.gz 100% |=========================| 127 kB 00:00 livna : ################################################## 380/380 Added 380 new packages, deleted 0 old in 1.36 seconds primary.xml.gz 100% |=========================| 371 kB 00:00 updates-re: ################################################## 1053/1053 Added 0 new packages, deleted 13 old in 0.93 seconds yum has set up the installation process and integrated online repositories for the installation of software. This feature is the reason why Fedora does not need a URL source for installing OpenVPN. The repository metadata contains information about location, availability, and dependencies between packages. Resolving the dependencies is the next step. Parsing package install arguments Resolving Dependencies --> Populating transaction set with selected packages. Please wait. ---> Downloading header for openvpn to pack into transaction set. openvpn-2.0.9-1.fc5.i386. 100% |=========================| 18 kB 00:00 ---> Package openvpn.i386 0:2.0.9-1.fc5 set to be updated --> Running transaction check --> Processing Dependency: liblzo.so.1 for package: openvpn --> Restarting Dependency Resolution with new changes. --> Populating transaction set with selected packages. Please wait. ---> Downloading header for lzo to pack into transaction set. lzo-1.08-4.i386.rpm 100% |=========================| 3.2 kB 00:00 ---> Package lzo.i386 0:1.08-4 set to be updated --> Running transaction check Dependencies Resolved OpenVPN needs the LZO library for installation, and yum is about to resolve this dependency. As a next step, yum tests whether this library has unresolved dependencies. If this is not the case, we are presented with an overview of the packages to be installed. Confirm by entering y and press the Enter key. yum will start downloading the required packages. If the RPM process that yum is using to install the software packages encounters a missing encryption key, then confirm the import of this key from http://www.fedoraproject.org by entering y and pressing the Enter key. This GPG key is used to control the authenticity of the packages selected for installation. Key imported successfully Running Transaction Test Finished Transaction Test Transaction Test Succeeded Running Transaction Installing: lzo ######################### [1/2] Installing: openvpn ######################### [2/2] Installed: openvpn.i386 0:2.0.9-1.fc5 Dependency Installed: lzo.i386 0:1.08-4 Complete! [root@fedora etc]# That's all! yum has been downloaded, checked, and has installed OpenVPN and the LZO libraries.
Read more
  • 0
  • 0
  • 9773

article-image-installing-openvpn-linux-and-unix-systems-part-2
Packt
31 Dec 2009
7 min read
Save for later

Installing OpenVPN on Linux and Unix Systems: Part 2

Packt
31 Dec 2009
7 min read
Installing OpenVPN on Debian and Ubuntu Probably the easiest distribution on which to install OpenVPN is Debian and its derivates like Ubuntu. Just type apt-get install openvpn, answer two questions, and OpenVPN is installed and ready to be used. The Debian package management system is capable of solving all the issues that might occur during the installation. If your system is configured correctly, then the automatic installation will cover the following steps: The installation helper apt-get will find the software on the installation servers. The helper will then download the chosen package and unpack it to your local system. An interactive configuration script is executed, which configures your system and the newly installed software for later use with the parameters that you enter. The following code extract is the standard output of apt-get install openvpn on a Debian system. This output may vary depending on your previous software selection, and in many cases the LZO compression library will have to be installed. On some systems apt will install OpenSSL libraries, but in most cases, apt-get is able to solve all problems for you. debian01:~# apt-get install openvpnReading Package Lists... DoneBuilding Dependency Tree... DoneThe following NEW packages will be installed:openvpn0 upgraded, 1 newly installed, 0 to remove and 7 not upgraded.Need to get 293kB of archives.After unpacking 762kB of additional disk space will be used.Get:1 http://ftp.uni-erlangen.de testing/main openvpn 2.0.9 [293kB]Fetched 298kB in 1s (247kB/s)Preconfiguring packages ...Selecting previously deselected package openvpn.(Reading database ... 9727 files and directories currently installed.)Unpacking openvpn (from .../openvpn_2.0-9_i386.deb) ...Setting up openvpn (2.0-9) ...Restarting virtual private network daemon:.debian01:~# During this process, you will be prompted to answer the following two questions: You have to allow apt to create a TUN/TAP device for use by OpenVPN software. If you select No, your tunnels will not be created and your tunnel software won't work. The second question raises a security issue. OpenVPN software should be stopped during an update, so you have to select YES and hit return. You have to stop the old tunnel software when an update is running. All tunneling will be stopped, and your users will not be able to connect to your system during this time. From then on, all tunnels are created by the new OpenVPN software, including patches and bug fixes. This is the safe way to go. However, if you choose No, you risk that the old software and libraries are still running, even after the installation of new OpenVPN software. Bug fixes and patches of the new version may not apply to existing tunnels until they are started again. You may run into serious inconsistencies in your system, if you have several tunnels and they are running different versions of your software. Thus, it is safer to have a short time when users will not be able to connect. Installing Debian packages Software packages for Debian systems are provided in the so-called .deb file format. DEB files are usually stored in online repositories on FTP or web servers, and every Debian system holds a list of repositories that can be used for installation. You will find this list in /etc/apt/sources.list. The setup program base-config provides a menu-based configuration interface for apt. If you want to add source repositories to your Debian installation, type base-config and change to the menu configure apt. Select the country you live in and the repository of your choice. Select Ok. Now all the software packages of this server can automatically be installed on your system, simply by typing apt-get install <package>. A Debian package contains the software and information about it, such as name, version, description, contents, prerequisites, dependencies, and configuration scripts that are to be started after installation. Debian systems offer some very powerful programs with which you can control software installation very specifically. Listing all programs and options would go far beyond the scope of this article, but here is a short overview of some handy package management commands. Command Function apt-get remove <package> Removes the selected package from your system apt-get update Updates the list of packages available on the repositories listed in /etc/apt/sources.list apt-get upgrade Installs the latest available versions of all your installed software apt-get dist-upgrade Installs the latest available software related to your configuration dpkg-reconfigure Restarts/Starts the configuration script inside the package, which will bring up the menu-based dialogs in the same way as after installation apt-cache show <package> Prints detailed information about the software package dpkg -l <package> Prints information on the installed software package dpkg -L <package> Lists all files installed by the software package dpkg -i <file> Installs a local (.deb) file to your system dpkg -S <file> Prints information about the software package owning <file> apt-cache search <string> Searches apt database for packages containing <string> in their name and description These programs should solve all possible questions, issues, and problems concerning the installation of software on Debian systems. Just try these commands with the freshly installed OpenVPN package on your system. Type the command apt-cache show openvpn to receive information about the installed package. Using Aptitude to search and install packages Although the Debian command-line tools are very powerful, there are more programs that help you to retrieve and install software. Probably the most common software for this purpose is Aptitude. Type aptitude in a command line in order to start the menu-based installation interface. If Aptitude is not installed on your system, type apt-get install aptitude. If you prefer aptitude, you can use it at the command line in the same way as apt-get. Aptitude consists of a menu at the top of the screen, a list of packages, and a window showing details on the software selected in the package list. If you have console mouse support, you can click on menu entries. Click on the menu entry Search, or hit the F10 key and navigate through the Search menu. Select the entry Find. You will be prompted with a search mask. Enter openvpn. While you are typing, Aptitude is steadily updating the main window. Click on OK and have a look at the output. Aptitude will find the OpenVPN version that you had installed previously, and the entries in the menus Actions and Package help you to select and install software. Depending on the selection of repositories that you have added to your sources.list during installation, Aptitude can also help you to choose different versions of OpenVPN. OpenVPN—the files installed on Debian The following table gives an overview of the files that were installed by the Debian package management system. Full path and file Installed by OpenVPN Function /etc/openvpn Directory containing configuration files /etc/network/if-up.d/openvpn /etc/network/if-down.d /etc/network/if-down.d/openvpn Start/stop openvpn when the network goes up/down /etc/init.d/openvpn Start/stop script for services /sbin/openvpn The binary /usr/share/doc/openvpn Documentation files /usr/share/man/man8/openvpn.8.gz Manual page /usr/share/doc/openvpn/examples/ sample-config-files Example configuration files /usr/share/doc/openvpn/examples/ sample-keys Example keys /usr/share/doc/openvpn/examples/ easy-rsa easy-rsa-a collection of scripts useful for creating tunnels /usr/share/doc/openvpn/ changelog.Debian.gz /usr/share/doc/openvpn/changelog.gz   Version history /usr/share/openvpn/verify-cn verify-cn function (revoke command) /usr/lib/openvpn/ openvpn-auth-pam.so /usr/lib/openvpn/ openvpn-down-root.so Libraries for PAM-Authentication and chroot mode  
Read more
  • 0
  • 0
  • 3080

article-image-searching-data-microsoft-dynamics-ax-2009-part-1
Packt
31 Dec 2009
10 min read
Save for later

Searching for Data in Microsoft Dynamics AX 2009: Part 1

Packt
31 Dec 2009
10 min read
Queries Queries are typically used to ask users about ranges and sorting, and then selecting data based on the feedback from the users. A query can consist of one or multiple data sources, and can be created both as static queries in the AOT or as dynamic queries using X++. Most commonly they are used when the ranges or values are not known until runtime. Static queries are defined in the AOT, whereas dynamic queries are defined in X++ code. Creating a static query using the AOT Follow these steps to create a static query in the AOT: Open the AOT, expand the Queries node, right-click on Queries, and select New Query. A new query is then created in the AOT. Right-click on the query, select Properties, and change the name to CarList (or in other cases, to something that describes what kind of data the query is returning). Open a new AOT window, expand the DataDictionary node, and then expand the Tables node. Drag the CarTable and drop it onto the Data Sources node of the new query. You can also drag maps or views to the data source of a query. You have now created the skeleton of the query. Let's now look at how to add sorting and ranges to the query. Adding a sort order to the query To add a sorting to the query, just drag the selected field from the Fields node under the data source and drop it under the Order By node. In our example, we'll use the Mileage field. You can then select to have it sort ascending or descending by changing the direction property on the sort field. When the query prompt is executed in a report, the user has the ability to change the sort order. Adding a range to the query You can also add ranges to the data source by dragging a field from the Fields node and dropping it onto the ranges. A range can be used to narrow down the result returned by the query, or it can be used as a fixed range that the user cannot change. This is done by adding a value to the value property of the range. Values in a range can be used like this: Range operator Description Example , Selects records where the range field matches any of the values listed BMW, VW, Volvo = Selects records where the range field is a matching value =VW .. Selects records where the range field is between the values specified including the values used. 1000..3000 < Selects records where the range field is less than the value specified <2000 > Selects records where the range field is greater than the value specified >2000 ! Selects records where the range field is not equal to the value specified !BMW ? Selects records where the ? can be any character Merc??es * Selects records where the range field matches the characters before or after the asterisk Merc* When the Status property is set to Open, the users can change the range value. If it's set to Lock, the users can see the range value before executing the query, but they are not allowed to change it. If the status property is set to Hide, the users won't even be allowed to see the range value. In our example, we add the ModelYear field from the data source CarTable_1: Joining data sources in a query In order to select data from more than one table, you can join the data sources in your query. Data sources can be joined in a couple of different ways depending on how you would like to link them. This is done by setting the JoinMode property to the different values shown in the following table: JoinMode Description InnerJoin Will return the records where the joined data sources have matching values in the joined fields. Ex: By using the CarTable as the primary data source and using RentalTable as the joined data source, the inner join will fetch all records from the CarTable where there is a corresponding record in the RentalTable. The corresponding records in RentalTable will also be fetched. OuterJoin Will return all the records from the joined table even if they don't match the joined field. Ex: Compared to the example using the InnerJoin, this will return all records from the CarTable, but also records from the RentalTable that does not have a match in the CarTable. ExistsJoin This is just like the InnerJoin, except the records from the joined data source are not returned. They are only used to filter the primary data source. Ex: In our example it will only return records in the CarTable where there is a match in the RentalTable. Records from the RentalTable will not be fetched. NoExistsJoin This is the opposite of ExistsJoin. It will select records from the primary data source when matching records in the joined data source does not exist. Ex: In our example it will return records from the CarTable that did not have any matching records in the RentalTable. (Cars that has never been rented) Follow these steps to add a new data source and join it with the first one: First, we will create a duplicate of the query that we have created so far, as we would like to use the original query in the Reporting Services report. To duplicate any AOT object, right-click on the object and select Duplicate. A duplicate is then created with the prefix CopyOf. Now rename the new query to RentalCarList. Also, change the range under the CarTable_1 data source to ModelYear instead of Model. This range will be used later in this article. Drag another table, map, or view, and drop it onto the Data Sources node below the first data source. In our example, we will add the RentalTable. Therefore, open a new AOT window and browse to Data Dictionary | Tables | RentalTable. Drag the RentalTable and drop it onto the Data Sources node under the CarTable data source in the query. Open the properties of the RentalTable data source in the query and change the Relations property to Yes. If you expand the Relations node under the RentalTable data source, you should now see that the CarTable data source is linked to the RentalTable data source by the CarId. Your AOT should look like this: Creating a dynamic query using X++ A query can also be built dynamically using X++ code. This can be the only way of creating the query, if you would like the query to work in one way in some cases and in another way in other cases. An example can be where you would like to join one table if one condition is true and another table if the condition is false. To do this, you need to understand how the query object model works. The most commonly used classes in the query object model are: Query: Contains the definition of the query. Can consist of one data source or several data sources if they are related. QueryRun: Class used to execute the query and loop through the result. QueryBuildDataSource: Links to one data source in the query. Can be linked to another QueryBuildDataSource object to join linked data sources. QueryBuildRange: Enables the end user to limit the result by adding a value in the specified query range. QueryBuildFieldList: List of all the fields in data source. OneQueryBuildFieldList object for each QueryBuildDataSource. By default the property Dynamic is set to true so that all fields are returned. QueryBuildLink: Links two data sources in a join. Is set on the child data source. The query definition is set up by creating and linking objects from the query object model together. The following example shows how this is done in order to create a similar query as we did in the previous section of this article when we created a query called RentalCarList in the AOT. static void queryRentalCarList(Args _args){Query query;QueryBuildDataSource queryBuildDataSource1,queryBuildDataSource2;QueryBuildRange queryBuildRange;QueryBuildLink queryBuildLink;;// Create a new query objectquery = new Query();// Add the first data source to the queryqueryBuildDataSource1 = query.addDataSource(tablenum(CarTable));// Add the range to this first data sourcequeryBuildRange = queryBuildDataSource1.addRange(fieldnum(CarTable, ModelYear));// Add the second datasource to the first data sourcequeryBuildDataSource2 =queryBuildDataSource1.addDataSource(tablenum(RentalTable));// Add the link from the child data source to the//parent datasourcequeryBuildLink = queryBuildDataSource2.addLink(fieldnum(CarTable,CarId),fieldnum(RentalTable, CarId));} Using a query Ok, so now we have the query definition. But that doesn't help us much unless we are able to execute the query, right? This example uses the previous example and just adds the QueryRun object and loops through the result by using the next() method on the QueryRun object. static void queryRunRentalCarList(Args _args){Query query;QueryBuildDataSource queryBuildDataSource1,queryBuildDataSource2;QueryBuildRange queryBuildRange;QueryBuildLink queryBuildLink;QueryRun queryRun;CarTable carTable;RentalTable rentalTable;;// Create a new query objectquery = new Query();// Add the first data source to the queryqueryBuildDataSource1 = query.addDataSource(tablenum(CarTable));// Add the range to this first data sourcequeryBuildRange = queryBuildDataSource1.addRange(fieldnum(CarTable, ModelYear));// Set the rangequeryBuildRange.value("2008..");// Add the second datasource to the first data sourcequeryBuildDataSource2 =queryBuildDataSource1.addDataSource(tablenum(RentalTable));// Add the link from the child data source to the parent data//sourcequeryBuildLink = queryBuildDataSource2.addLink(fieldnum(CarTable,CarId),fieldnum(RentalTable, CarId));// Create a new QueryRun object based on the query definitionqueryRun = new QueryRun(query);// Loop through all the records returned by the querywhile (queryRun.next()){// Get the table data by using the get() methodcarTable = queryRun.get(tablenum(CarTable));rentalTable = queryRun.get(tablenum(RentalTable));info (strfmt("CarId %1, RentalId %2", carTable.CarId,rentalTable.RentalId));}} The following result is obtained after running the query: The exact same result will show up if we execute the query that was defined in the AOT in the previous section of this article. The code would then look like this: static void queryRunRentalCarListAOT(Args _args){Query query;QueryBuildDataSource queryBuildDataSource;QueryBuildRange queryBuildRange;QueryRun queryRun;CarTable carTable;RentalTable rentalTable;;// Create a new query object based on the Query in the AOT called//RentalCarListquery = new Query(querystr(RentalCarList));// Find the datasource for the CarTablequeryBuildDataSource = query.dataSourceTable(tablenum(CarTable));// Find the range that we added to the query in the AOTqueryBuildRange =queryBuildDataSource.findRange(fieldnum(CarTable, ModelYear));// Set the value of the rangequeryBuildRange.value("2008..");// Create a new QueryRun object based on the query definitionqueryRun = new QueryRun(query);// Loop through all the records returned by the querywhile (queryRun.next()){// Get the table data by using the get() methodcarTable = queryRun.get(tablenum(CarTable));rentalTable = queryRun.get(tablenum(RentalTable));info (strfmt("CarId %1, RentalId %2", carTable.CarId,rentalTable.RentalId));}} Views Views in AX are objects that are used to retrieve data from the database that is stored in the memory on the layer in which the view is instantiated. The views are actually stored as database views on the SQL server. This means that there are potentially great performance benefits of using views compared to using an equivalent query. This depends of course on the complexity of the query, but in general the performance benefits of using a view compared to a query will increase along with the complexity of the query. Views can be used throughout AX in all places where tables can be used. This includes forms, queries, reports, and X++ code. Views in AX can never be used to write data, only to read data from the database. This differs from the SQL implementation that has write-back possibilities for views.
Read more
  • 0
  • 0
  • 7287

article-image-searching-data-microsoft-dynamics-ax-2009-part-3
Packt
31 Dec 2009
5 min read
Save for later

Searching for Data in Microsoft Dynamics AX 2009: Part 3

Packt
31 Dec 2009
5 min read
Exists join An exists join does pretty much the same as the inner join, except one important thing; it does not fetch the records from the joined table. This means that the RentalTable variable cannot be used within the while loop in the following example, as it will never have any data: static void selectExistsJoin(Args _args){CarTable carTable;RentalTable rentalTable;;while select carTableexists join rentalTablewhere rentalTable.CarId == carTable.CarId{info(strfmt("CarId %1 has a matching record in rentalTable",CarTable.CarId));}} Executing this Job will result in the following output to the Infolog: NotExists join Obviously the notexists join is the opposite of the exists join. This means that it will return all records from the main table where there does not exist a record in the joined table as described by the where clause. This means that the following example will produce the opposite result from the previous example: static void selectNotExistsJoin(Args _args){CarTable carTable;RentalTable rentalTable;;while select carTablenotexists join rentalTablewhere rentalTable.CarId == carTable.CarId{info(strfmt("CarId %1 does not has a matching record inrentalTable", CarTable.CarId));}} Executing this job will result in the following output to the Infolog: Writing aggregate select statements In many cases, you would like to write select statements that return aggregate data like the sum or average of a field in a set of data. You can also use the count aggregate option to count the number of records in a table matching a where statement (if any). The minof and maxof options can be used in the same way to find the minimum or maximum value of a field in a record set that corresponds to the where statement. These examples show how the different aggregate options can be used: sum static void selectSumMileage(Args _args){CarTable carTable;;select sum(Mileage) from carTable;info(strfmt("The total mileage of all cars is %1",carTable.Mileage));} Executing this Job will result in the following output to the Infolog: avg static void selectAvgModelYear(Args _args){CarTable carTable;;select avg(ModelYear) from carTable;info(strfmt("The average ModelYear is %1",carTable.ModelYear));} Executing this Job will result in the following output to the Infolog: count static void selectCountRentals(Args _args){RentalTable rentalTable;;select count(recId) from rentalTable;info(strfmt("There are %1 rentals registerred in the system",rentalTable.RecId));} Executing this Job will result in the following output to the Infolog: minof and maxof static void selectCountRentalsPerCustomer(Args _args){RentalTable rentalTable;;// Normal while select to loop datainfo ("Using while select:");// The result of the count operation is put// into the recId field of the tableBuffer// since it is an integerfield.while select count(recId) from rentalTablegroup by rentalTable.CustAccount{info(strfmt(" Customer %1 has rented cars %2 times",rentalTable.CustAccount, rentalTable.RecId));}// Looping the rentalTable cusrsor using the next commandinfo ("Using next command:");select count(recId) from rentalTablegroup by rentalTable.CustAccount;while (rentalTable.RecId){info(strfmt(" Customer %1 has rented cars %2 times",rentalTable.CustAccount, rentalTable.RecId));next rentalTable;}}                                                                        Executing this Job will result in the following output to the Infolog: Group by In many cases, aggregate options are used together with the group by parameter in order to list the aggregate for each subpart of a table. In the next example we will find the number of rentals for each customer that has rented cars. I will also demonstrate how to use the next command together with the select statement instead of the while select statement to loop through the records in the result. You will most often see the while select statement being used in standard AX, but in case you see the next command, you will know it does the same as a while select statement. The following example shows how the group by aggregate option can be used: select carTable; // Is the same as select * from carTable Executing this Job will result in the following output to the Infolog: Optimizing the data retrieval There can be several different steps that you, as a developer, should take in order to optimize the process of fetching data from the database to the application. I will try to cover the most important things for you to keep in mind here. Using the correct data retrieval method One important issue, not only for optimization but also for usability, is to select the correct data retrieval method based on what you would like to achieve. Use queries when you want the users to be able to change the range of data to be retrieved and when the selection criteria are simple enough for the query to handle. If the selection criteria are complex, and there is no need for the users to be able to change the selection criteria, you should opt for a select statement. If you would like to be able to use the query definition multiple places, you should create a query in the AOT instead of writing it in X++ every time you need to use it. It can also be easier to get a visual overview of a query created in the AOT compared to a query written in X++. If the selection criteria is complex, there is no need for updating or deleting the data selected and if you would like to be able to use the same selection in many places in the application, then you should consider creating a view in the AOT instead of writing the select statement every time.
Read more
  • 0
  • 0
  • 2225
article-image-getting-started-spring-mvc-developing-mvc-components
Packt
31 Dec 2009
5 min read
Save for later

Getting Started With Spring MVC - Developing the MVC components

Packt
31 Dec 2009
5 min read
In the world of networked applications, thin clients (also known as web applications) are more in demand than thick clients. Due to this demand, every language is providing frameworks that try to make web-application development simpler. The simplicity is not provided just through setting up the basic application structure or generating boiler plate code. These frameworks are trying to provide simplicity through plug-ability of the frameworks i.e. the components of different frameworks could be brought together without much difficulty. Among such frameworks, Spring Framework is one of the most used. With its support to multiple Data Access frameworks/libraries and light-weight IoC container makes it suitable for scenarios where one would like mix-and-match multiple frameworks, a different one for each layer. This aspect of Spring Framework becomes more suitable for development of web-applications where the UI does not need to know with which framework it is dealing for business process or data access. The component of the Spring Framework stack that caters to the web UI is Spring MVC. In this discussion, we will focus on the basics of Spring MVC. First section will deal with the terms and terminologies related with Spring MVC and MVC. The second section will detail the steps for developing components of a web-application using Spring MVC. That is the agenda for this discussion. Spring MVC Spring MVC, as the name suggests, is a framework based on Model (M), View (V), Controller (C) pattern. Currently there are more than seven well known web-application frameworks that implement MVC pattern. Then what are the features of Spring MVC that sets it apart from other frameworks? The two main features are: Pluggable View technology Injection of services into controllers The former provides a way to use different UI frameworks instead of Spring MVC’s UI library and the latter removes the need to develop a new way to access functionality of business layer. Pluggable View technologyVarious View technologies are available in the market (including Tiles, Velocity, etc) with which Spring MVC can quite easily be integrated. In other words, JSP is not the only template engine supported. The pluggable feature is not limited to the templating technologies. By using common configuration functionality, other frameworks such as JSF can be integrated with Spring MVC applications. Thus, it is possible to mix-and-match different View technologies by using Spring MVC. Injection of Services into ControllersThis feature comes into picture when the Spring Framework is used to implement the business layer. Using the IoC capabilities of Spring Framework, the business layer services and/or objects can be injected into the Controller without explicitly setting up the call to the service or mirroring the business layer objects in controller. This helps in reduction of code duplication between Web UI/process layer and business process layer. The next important aspect of Spring MVC is its components. They are: Model (M) View (V) Controller (C) Model deals with the data that the application has to present, View contains the logic to present the data and Controller takes care of the flow of navigation and application logic. Following are the details. ModelModel is an object that holds the data to be displayed. It can be any Java object – from simple POJO to any type of Collection object. It can also be a combination of both – an instance of POJO to hold the detailed data and a collection object to hold all the instances of the POJO which, in reality, is most commonly used Model in Spring MVC. Also, the framework has its own way to hold the data. It holds the data using the Model object that is an instance of org.springframework.ui.ModelMap. Internally, whichever collection class object is used, the framework maps it to the ModelMap class. ViewIn MVC, it is the View that presents the data to the user. Spring MVC, just as many other JEE frameworks, uses a combination of JSP and tag libraries to implement View. Apart from using JSP, many kinds of View technologies like Tiles, Velocity, and Jasper Reports can be plugged into the Framework. The main class behind this plug ability is the org.springframework.web.servlet.View. The View class achieves the plug-in functionality by presenting the View as Logical View instead of actual/physical View. Physical view corresponds to the page developed using any of the templating technologies. The Logical View corresponds to the name of the View to be used. The name is then mapped to the actual View in the configuration file. One important point to remember about how Spring MVC uses Logical View is that Logical View and Model are treated as one entity named Model And View represented by org.springframework.web.servlet.ModelAndView class. ControllerThe flow of application and navigation is directed by the controller. It also processes the user input and transforms it into the Model. In Spring MVC, controllers are developed either by extending the out-of-the-box Controller classes or implementing the Controller interface. Following comes under the former category SimpleFormController AbstractController AbstractCommandController CancellableFormController AbstractCommandController MultiActionController ParameterizableViewController ServletForwardingController ServletWrappingController UrlFilenameViewController Of these most commonly used are AbstractController, AbstractCommandController, SimpleFormController and CancellableFormController. That wraps up this section. Let us move onto the next section – steps for developing an application using Spring MVC.
Read more
  • 0
  • 0
  • 2726

article-image-searching-data-microsoft-dynamics-ax-2009-part-2
Packt
31 Dec 2009
5 min read
Save for later

Searching for Data in Microsoft Dynamics AX 2009: Part 2

Packt
31 Dec 2009
5 min read
Select statement One of the great features of Dynamics AX as a development tool is the possibility to write embedded SQL. This basically means that you can write select statements that are controlled by the compiler and get results back directly to table variables. The following list is taken from the SDK and shows the syntax for the select statement and the parameters allowed with the select statement: Desciption Syntax SelectStatement select Parameters Parameters [ [ FindOptions ] [ FieldList from ] ] TableBufferVariable [ IndexClause ] [ Options ] [ WhereClause ] [ JoinClause ] FindOptions crossCompany | reverse | firstFast | [ firstOnly | firstOnly10 | firstOnly100 | firstOnly1000 ] | forUpdate | noFetch | [forcePlaceholders | forceLiterals] | forceselectorder | forceNestedLoop | repeatableRead FieldList Field { , Field } | * Field Aggregate ( FieldIdentifier ) | FieldIdentifier Aggregate sum | avg | minof | maxof | count Options [ order by , group by , FieldIdentifier [ asc | desc ] { , FieldIdentifier [ asc | desc ] }] | [ IndexClause ] IndexClause index IndexName | index hint IndexName WhereClause where Expression JoinClause [exists | notexists | outer ] join Parameters Check out the SDK for a more in-depth explanation of all the different keywords. In the following examples, we will have a look at how to create different select statements depending on what data we would like to have available for the rest of the code. To have a better understanding of how the different select statements work and what data is returned, we will use the following data: CarTable The following table shows the test data for the CarTable: CarId ModelYear CarBrand Model Mileage 1 2007 BMW 320 2299 2 2007 Mercedes C220 2883 3 2008 Toyota Corolla 4032 4 2006 Vokswagen Golf 49902 5 2002 Jeep Grand Cherokee 65662 6 2003 BMW Z3 11120 7 2000 Volkswagen Golf 76322 RentalTable The following table shows the test data for the RentalTable: RentalId CustAccount FromDate ToDate CarId 1 1101 24.03.2009 25.03.2009 1 2 1103 23.03.2009 25.03.2009 3 3 1103 02.05.2009 11.05.2009 1 4 1102 10.05.2009 17.05.2009 5 5 1104 10.12.2009 20.12.2009 6 CustTable The following table shows the test data for the CustTable: Account Num Name CustGroup Blocked 1101 Forest Wholesales 10 No 1102 Sunset Wholesales 20 No 1103 Cave Wholesales 10 No 1104 Desert Wholesales 30 Yes Writing a simple select statement A select statement can be written specifically to return only one record or to return many records. If we expect the select statement to return multiple records and we would like to loop through these records, we simply embed the select statement within a while loop. The following examples will demonstrate how to write simple select statements that return different data from the same table. The first example will select all columns from all records in the CarTable as shown in the following Job: static void selectAllRecordsStatic(Args _args){CarTable carTable;int records;;info("------------------START-------------------");while select carTable{info("--------------NEW RECORD--------------");info (strfmt("CarId: %1", carTable.CarId));info (strfmt("CarBrand: %1", carTable.CarBrand));info (strfmt("Model: %1", carTable.Model));info (strfmt("ModelYear: %1", carTable.ModelYear));info (strfmt("Mileage: %1", carTable.Mileage));records++;}info("------------------END-------------------");info(strfmt("%1 records was selected", records));} Executing this Job will result in the following output to the Infolog. Note that only the first records are shown in the Infolog window. When executing it yourself, you can scroll down to see the other records at the end line. The Infolog screen is shown in the following screenshot: The next example actually does pretty much the same as the first example, but I have added some code to be able to dynamically write the fields in the table. It will also print all the systems fields for each record, but it can be a nice exercise for you to understand how you can use the Dict classes to create dynamic functionality, as shown in the following Job: static void selectAllRecordsDynamically(Args _args){CarTable carTable;DictField dictField;DictTable dictTable;int field;int fieldId;int records;str header, line;;// Create a new object of type DictTable based on the carTabledictTable = new DictTable(tablenum(carTable));// Loop through the fields on the table.// For each field, store the field-label in the header variable.for (field=1; field <= dictTable.fieldCnt(); field++){fieldId = dictTable.fieldCnt2Id(field);dictField = new DictField(tablenum(carTable), fieldId);header += strfmt("%1, ", dictField.label());}info(strupr(header)); // strupr changes the string to UPPERCASE// Loop through all the records in the carTablewhile select carTable{line = "";// For each record in the carTable, loop through all the//fields// and store the value of the field for this record in the//line variable.for (field=1; field <= dictTable.fieldCnt(); field++){fieldId = dictTable.fieldCnt2Id(field);dictField = new DictField(carTable.TableId, fieldId);// Instead of referencing to the fieldname, I reference to//field ID// to get the fields value.line += strfmt("%1, ", carTable.(fieldId));}info(line);records++;}info(strfmt("%1 records were selected", records));} Executing this Job will result in the following output to the Infolog: The next example will select all columns from the record in CarTable where the CarId equals 1. This means that we will only select one record and hence, we do not need the while loop: static void selectOneRecord(Args _args){CarTable carTable;;select firstonly carTablewhere carTable.CarId == "1";info (strfmt("Car Brand: %1", carTable.CarBrand));info (strfmt("Car Model: %1", carTable.Model));info (strfmt("Model Year: %1", carTable.ModelYear));info (strfmt("Mileage: %1", carTable.Mileage));} Executing this Job will result in the following output to the Infolog: The next example will select only the CarBrand and the Model columns from all records in the CarTable where the ModelYear is greater than 2005: static void selectWhereStatement(Args _args){CarTable carTable;;info(strupr("CarBrand, Model"));while select CarBrand, Model from carTablewhere carTable.ModelYear > 2005{info (strfmt("%1, %2 ", carTable.CarBrand, carTable.Model));}} Executing this Job will result in the following output to the Infolog: Executing this Job will result in the following output to the Infolog: Microsoft Dynamics AX 2009 Programming: Getting Started
Read more
  • 0
  • 0
  • 2080

article-image-configuring-jms-resources-glassfish-part-1
Packt
31 Dec 2009
10 min read
Save for later

Configuring JMS Resources in GlassFish: Part 1

Packt
31 Dec 2009
10 min read
JMS support on GlassFish Message-based solutions are playing an increasingly important role nowadays, as more and more systems need to be integrated together and need to communicate with each other in a loosely-coupled manner. In this section, we briefly introduce the core concepts of messaging system and the JMS standard, and then describe how GlassFish supports JMS resources. Message-based systems and JMS A simplified view of a typical message-based system is illustrated in the following figure. As shown in the figure, the communication pattern of a messaging-based system is different from the client-server paradigm, where application components communicate with each other directly. Instead, in a message-based system, the communication among application components (producers and consumers) is mediated by a message service provider. As a result of this, a message service provider is sometimes referred to as a Message Oriented Middleware (MOM). The producer creates a message that contains relevant data, and sends it to a destination resource maintained by the message service provider. The message is then routed to consumer components that are registered to the specific destination. Another distinct feature of a message-based system is that the message service provider effectively makes the communication between producers and consumers asynchronous. When a producer sends a message, consumers do not need to be available because the message service provider can persist the message until the consumer becomes available. In fact, the producer and consumer do not need to have any knowledge of each other, as long as the message is in a format that is agreed upon. This feature further decouples the producers and consumers. JMS defines a standard Java API for application components to create, send, receive, and process messages. It also provides a standard API that simplifies how application components interact with a JMS-compliant message service provider (JMS provider for short). It defines the connection factory and destinations of the JMS provider in the form of administered objects, which can be registered in a JNDI naming service. An application component can use the standard JNDI API to perform a lookup operation to retrieve these resources. This approach reduces the vendor-dependency when we build a JMS application. JMS defines the two messaging approaches as follows: Point-to-Point (PTP): A producer sends messages to a queue destination, which retains the messages until they are successfully routed to a consumer. Furthermore, each message is received by only one consumer. Publish/Subscribe (Pub/Sub): A producer sends messages to a topic destination. By default, the topic does not retain these messages. Instead, it immediately routes them to all the consumers registered for the topic. Due to this, if a message arrives at a topic when there is no active consumer, the message will be lost. To address this, JMS allows a consumer to be registered to the topic as durable subscriber. In this case, the JMS provider will retain the messages for this consumer until it becomes available. The JMS API became an integral part of the Java EE since version 1.3 as the standard to integrate with messaging systems. Subsequent Java EE revisions further enhanced the JMS API and messaging system integration in the following areas: Message-Driven Beans (MDB): An MDB is a container-managed component that can asynchronously consume messages sent to a JMS destination. Due to this, we can consider an MDB as an asynchronous message listener component. The application server's MDB container provides services for MDBs such as life cycle management, instance pooling and naming services. These services eliminate a lot of boiler-plate code necessary to create a message listener object. Due to this, when implementing an MDB, the developer only needs to focus on the logic about how to process messages delivered to the MDB. Furthermore, the MDB container's instance pooling service can significantly improve the throughput of processing messages routed to a specific MDB. Java Connector Architecture (JCA): Through JCA resource adapters, JMS providers can be easily integrated into different application servers. Once integrated, application components can treat them as standard JCA resources, and interact with the resources in a provider-independent manner. GlassFish support for JMS The GlassFish Server contains a built-in JMS service provider, the Open MQ (https://mq.dev.java.net). It also includes a generic JCA resource adapter that can be used to integrate with most JMS providers. GlassFish also provides a configurable MDB container implementation to host message driven beans. In this article, we discuss how GlassFish integrates with two different JMS providers—the Open MQ and Apache ActiveMQ (http://activemq.apache.org). We also discuss how we can configure the MDB container and MDB components to work with a JMS service provider. One of the most commonly asked questions is "Which JMS provider is better, or at least which open source JMS provider is better?". The answer to this question typically depends heavily on the experience of the individual or organization. Most reputable JMS implementations, including Open MQ and ActiveMQ are capable of processing large volumes of messages efficiently. Between Open MQ and ActiveMQ, my personal favorite choice is the former. The reason is not because Open MQ is bundled in GlassFish. It is actually because my experience with the Open MQ product dates back to the days of its commercial ancestor, the Sun ONE Message Queue. I have always appreciated its straightforward administration interface and thorough documentation. Furthermore, I have successfully created many production deployments by using the product. Make no mistake though; I have also witnessed organizations using ActiveMQ successfully in production. Also, ActiveMQ is under active development, and it is bundled in several very good open source products as the default JMS provider. Now, let's discuss how GlassFish works with the Open MQ product (https://mq.dev.java.net). Getting started with Open MQ An evolution of the Sun Java System Message Queue (formerly Sun ONE Message Queue), Open MQ is a very active open source sub-project of GlassFish. Open MQ implements a high-performance JMS provider. In addition to its high performance, and being fully JMS compliant, Open MQ provides many other features, such as message broker cluster support, SOAP/HTTP message support, C/C++ Client API support, and so on. Due to this, some people said Open MQ was the best kept secret within the Sun middleware software stack. The GlassFish Server is shipped with the Open MQ product. In addition, the GlassFish administration infrastructure provides some basic capabilities for configuring the Open MQ. The open source distribution of the GlassFish server you download from the GlassFish project site includes the "community edition" of Open MQ. This edition does not include some of the additional features such as C-API support. If you need to use these features, you can either download or install the Sun supported GlassFish Enterprise Server distribution, or download and install a full version of the Open MQ product. We should expect that in future versions of GlassFish, the bundled Open MQ will be a feature-complete distribution. By default, the bundled Open MQ is configured to have a small footprint without many advanced features. In this section, we will first get familiar with the Open MQ product, and later in this article we will show you how to configure the Open MQ to work with GlassFish and Java EE application components. First, let's examine the high-level architecture of GlassFish, and learn the meaning of some critical concepts along the way. The architecture of Open MQ The high-level architecture of Open MQ is illustrated in the following figure. The main components illustrated in this figure are explained as follows: The Broker can be considered as a complete instance of the message provider. A broker contains physical destinations (both queues and topics), and it is responsible for routing messages sent from producers to the appropriate destination, and delivering messages from destinations to registered consumers. The broker supports multiple connection mechanisms between application components and the broker, and it can also be configured with different performance and security features. In order to simplify and standardize the JMS programming model, JMS defines two types of administered objects—connection factories and destinations. A Connection Factory is an object that encapsulates all the vendor-specific information necessary for a client to establish a connection to the broker, and the destination object provides a logical reference to a physical destination. These two administered objects are registered in a JNDI-compliant object store, and a client can perform a standard JNDI lookup to retrieve these objects. Once these objects are retrieved, the client can produce and consume messages. A client can create these objects programmatically. For example, a client may want to use some vendor-specific features or APIs that cannot be encapsulated in a standard manner. However, this practice is highly discouraged. The directory structure of Open MQ The binary of the Open MQ software bundled with GlassFish is installed at$AS_INSTALL/imq. The high-level directory structure and essential files are described as follows: The bin directory contains the command line and GUI utilities for administering and controlling the MQ. The essential utilities include: imqadmin: The Open MQ GUI-based administration console. imqbrokerd: The broker management utility. imqcmd: The command-line administration utility of Open MQ. imqdbmgr: The utility to manage a JDBC-based message store. imqkeytool: The utility to generate self-signed SSL certifi cate for a broker. imqobjmgr: The utility to manage administered objects, including connection factory and destinations. imqusermgr: The utility to manage the flat file user repository for the Open MQ. The demo directory contains a variety of demo applications for Open MQ. The etc directory contains the Open MQ server-wide configuration file— imqenv.conf. This file effectively defines the environment variables for the Open MQ installation. For example, you should find the following line near the end of the file:IMQ_DEFAULT_VARHOME=/opt/glassfish/domains/domain1/imq This line specifi es that by default, all the brokers created within this Open MQ installation will be inside the /opt/glassfish/domains/domain1/imq directory. The include directory contains the C API header files for building C-based clients. The javadoc contains the Java API documentation for Open MQ. The lib directory contains the Java and C libraries for the Open MQ. The var directory is empty. In a standalone installation, this directory is the default root directory for all the brokers created. Once GlassFish is installed, a default OpenMQ broker, imqbroker is also created within the default domain in $AS_INSTALL/domains/domain1/imq/instances/imqbroker. The main content of this directory includes: The etc directory contains two files, the passwd is a password file for users configured for the broker, and the accesscontrol.properties file allows us to specify different types of access controls for different users. The fs370 directory is the flat file-based persistence store for messages and transactions. The log directory contains the rotated log files of running the broker. The props directory contains the config.properties file, which describes most of the properties configured for the broker. In the following section, we show you how to configure Open MQ.
Read more
  • 0
  • 0
  • 6268
article-image-editing-datagrids-popup-windows-flex
Packt
31 Dec 2009
4 min read
Save for later

Editing DataGrids with Popup Windows in Flex

Packt
31 Dec 2009
4 min read
To start with we'll create a DataGrid which will contain a first name and a last name. We will add a Panel container to place our DataGrid into. Here is what our initial app looks like: <?xml version="1.0" encoding="utf-8"?> <mx:Application layout="absolute"> <mx:Panel title="Pop Up Window" > <mx:DataGrid width="100%" height="100%"> <mx:columns> <mx:DataGridColumn headerText="First Name"/> <mx:DataGridColumn headerText="Last Name"/> </mx:columns> </mx:DataGrid> </mx:Panel> </mx:Application> You'll notice the common Application tag along with the Panel. Immediately inside the Panel is our all important DataGrid. Note, if you are not familiar with the basics of Flex then stop here and head over to the Adobe site for an introduction. Although this tutorial is not complex, I wont be able to focus on the fundamentals. I've set the DataGrid width and height attibutes to 100%. This will force it to expand to the size and width of the panel. You can make this application full screen by setting the same attributes on the Panel tag. Inside our DataGrid tag is the columns tag. Here we can describe what each column of our DataGrid will contain. In this case, one column for first name and one column for the last name. Here is a first look at our app: Adding Data The ease of Flex has allowed us to create this simple user interface with little effort. Now we come to a point where we need to add data to the DataGrid. The easiest way to do this is to use the dataProvider attribute. We will add an ArrayCollection Object to the script portion of our application to hold all the names which will appear in our DataGrid. The DataGrid and the accompanying ArrayCollection will look something like this: <mx:DataGrid id="names" width="100%" height="100%" dataProvider="{namesDP}"> <mx:columns> <mx:DataGridColumn headerText="First Name" dataField="firstName"/> <mx:DataGridColumn headerText="Last Name" dataField="lastName"/> </mx:columns> </mx:DataGrid> [Bindable] public var namesDP:ArrayCollection = new ArrayCollection ([ {firstName:'Keith',lastName:'Lee'}, {firstName:'Ira',lastName:'Glass'}, {firstName:'Christopher',lastName:'Rossin'}, {firstName:'Mary',lastName:'Little'}, {firstName:'Charlie',lastName:'Wagner'}, {firstName:'Cali',lastName:'Gonia'}, {firstName:'Molly',lastName:'Ivans'}, {firstName:'Amber',lastName:'Johnson'}]); The dataProvider attribute binds the DataGrid to the nameDP ArrayCollection. The ArrayCollection constructor's argument is an array of objects. Each object has a firstName and lastName property. If you wanted to expand on this application, you can add more data to this Array. You should also notice that the DataGridColumn tags also have an addition. We've set the dataField equal to the property in the dataProvider. The dataField is the real key in populating the DataGrid. Here is what our populated DataGrid looks like: We've now created the foundation of our application. Activating the DoubleClick Event By default the DataGrid doubleclick event is turned off. This means when a user doubleclicks an entry nothing will happen. In order to tell the DataGrid to trigger the doublelcick event we need to set the doubleClick and doubleClickEnabled attributes of the DataGrid tag. It looks like this: <mx:DataGrid width="100%" height="100%" doubleClick="showPopUp(event)" doubleClickEnabled="true"> I've set the doubleClick attribute to a method called showPopUp. We've not written this method yet, but it will be responsible for displaying the PopUp window which will allow editing of the DataGrid data. For now, let's add the Script tag and an empty showPopUp method: <mx:Script> <![CDATA[ import mx.events.ItemClickEvent; public function showPopUp(event:MouseEvent):void{ // show the popup } ]]> </mx:Script> The Script tag is a child of the Application tag.
Read more
  • 0
  • 0
  • 2873

article-image-uploading-videos-and-sound-files-your-posts-using-apache-roller-40
Packt
30 Dec 2009
6 min read
Save for later

Uploading Videos and Sound Files on Your Posts Using Apache Roller 4.0

Packt
30 Dec 2009
6 min read
Using videos in your posts It's time to learn how to insert video files in your posts. You can just insert one as an HTML link, but who does that anymore? It's a good way to drive your prospective readers away! In today's world, you need to offer your spectators the easiest, quickest, and most attractive way to see what you have to offer. My job is to show you how to do that with your Roller weblog, so let's get to it! Time for action – uploading and inserting videos on your posts In this exercise, I'll show you how to upload a video file to your blog server and then insert it into a post using Apache Roller: Open your web browser and log into Roller. The New Entry page will appear. Click on the File Uploads link from the Create & Edit tab. Scroll down the File Uploads page until you locate the Manage Uploaded Files section. Type video in the New Directory field and click on the Create button, as shown in the following screenshot:  Roller will show the following success message: Scroll down the page again until you locate the video folder in the Manage Uploaded Files section, and click on it: Roller will take you to the same File Uploads page, but this time you'll be inside the video directory. Now click on the first Browse... button of the Upload files for use in weblog main section. On the File Upload dialog, go to the folder where you downloaded the support files for this article, and double-click on the FirstFrame.png image to select it. The name of this file will show up on the first textbox of the File Uploads page. Now click on the second Browse... button and double-click on the showvbox.mp4 file, so that its name appears in the second textbox of the File Uploads page. Repeat the process with the third Browse... button and the showvbox_controller.swf file. Your File Uploads page must look like the following screenshot: Click on the Upload button to upload the three files to the video directory in your blog server. Roller will return the following success page: Don't forget to write down the three URLs from the previous Roller message; you'll need them when inserting the video into an entry (post). Click on the New Entry link from the Create & Edit tab to go to the New Entry page and create a new post for your blog. Type Ubuntu Linux Virtual Machine Inside a Windows XP PC in the Title field, select Open Source in the Category field, type virtualbox windows xp linux ubuntu in the Tags field. In the Content field, and type Here's a sample video of my Ubuntu Linux Virtual Machine, running inside a Windows XP PC with VirtualBox: as shown in the following screenshot:   Click on the Toggle HTML Source button from the HTML editor and write the following code below the text you typed in step 8 (the text in bold must correspond to the URLs from step 7's screenshot): <object height="498" width="640" id="csSWF" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/ cabs/flash/swflash.cab#version=9,0,115,0"><param name="src" value="http://localhost/roller/main/ resource/video/showvbox_controller.swf" /><param name="bgcolor" value="#1a1a1a" /><param name="quality" value="best" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><param name="scale" value="showall" /><param name="flashVars" value="autostart=false" /><embed height="498" width="640" name="csSWF" src="http://localhost/roller/main/resource/ video/showvbox_controller.swf" bgcolor="#1a1a1a" quality="best" allowscriptaccess="always" allowfullscreen="true" scale="showall" flashvars="autostart=false&amp; thumb=http://localhost/roller/main/resource/ video/FirstFrame.png&amp; thumbscale=45&amp;color=0x000000,0x000000" pluginspage="http://www.macromedia.com/ shockwave/download/ index.cgi?P1_Prod_Version=ShockwaveFlash"/></object> Click on the Save as Draft button, to save a draft of your post. Then scroll down the page and click on the Full Preview button, to see how your post will look in your blog before publishing it. The preview will open in a new tab in your web browser:       Click on the play button and the video will begin to playback. When finished, close the preview tab and click on the Post to Weblog button to publish your new post. You can logout from Roller now. What just happened? The previous exercise showed you how to upload a video to your blog server and insert it in a post. As you can see, videos are a little more complicated than plain images. In this case, we used the following files: FirstFrame.png: This is the thumbnail image that shows up before the video begins to playback showvbox.mp4: The video file showvbox_controller.swf: The controller that plays back theshowvbox.mp4 file      The video was produced with Camtasia Studio, an excellent screen recording software application from TechSmith (http://www.techsmith.com). If you want to practice with your own videos, you can download a 30-day free trial version of Camtasia Studio from the following URL: http://www.techsmith.com/download/camtasiatrial.asp. What would happen if you wanted to embed a video from your camera or cell phone? Well, you can embed it directly in your blog, but the best thing to do is use a software application such as Camtasia Studio to create the .swf controller and the HTML code to embed into your post automatically. Then you just need to change the .swf controller and thumbnail URLs, as you did in step 9 of the previous exercise. You can use the same embed code to insert a different video in your blog; just be sure to change the URL in bold text. You could also upload your video to YouTube instead of uploading it into Roller, as we'll see later in this article.
Read more
  • 0
  • 0
  • 5004
Modal Close icon
Modal Close icon