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
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Server-Side Web Development

406 Articles
article-image-phalcons-orm
Packt
25 Aug 2015
9 min read
Save for later

Phalcon's ORM

Packt
25 Aug 2015
9 min read
In this article by Calin Rada, the author of the book Learning Phalcon PHP, we will go through a few of the ORM CRUD operations (update, and delete) and database transactions (For more resources related to this topic, see here.) By using the ORM, there is virtually no need to write any SQL in your code. Everything is OOP, and it is using the models to perform operations. The first, and the most basic, operation is retrieving data. In the old days, you would do this: $result = mysql_query("SELECT * FROM article"); The class that our models are extending is PhalconMvcModel. This  class has some very useful methods built in, such as find(), findFirst(), count(), sum(), maximum(), minimum(), average(), save(), create(), update(), and delete(). CRUD – updating data Updating data is as easy as creating it. The only thing that we need to do is find the record that we want to update. Open the article manager and add the following code: public function update($id, $data) { $article = Article::findFirstById($id); if (!$article) { throw new Exception('Article not found', 404); } $article->setArticleShortTitle($data[ 'article_short_title']); $article->setUpdatedAt(new PhalconDbRawValue('NOW()')); if (false === $article->update()) { foreach ($article->getMessages() as $message) { $error[] = (string) $message; } throw new Exception(json_encode($error)); } return $article; } As you can see, we are passing a new variable, $id, to the update method and searching for an article that has its ID equal to the value of the $id variable. For the sake of an example, this method will update only the article title and the updated_at field for now. Next, we will create a new dummy method as we did for the article, create. Open modules/Backoffice/Controllers/ArticleController.php and add the following code: public function updateAction($id) { $this->view->disable(); $article_manager = $this->getDI()->get( 'core_article_manager'); try { $article = $article_manager->update($id, [ 'article_short_title' => 'Modified article 1' ]); echo $article->getId(), " was updated."; } catch (Exception $e) { echo $e->getMessage(); } } If you access http://www.learning-phalcon.localhost/backoffice/article/update/1 now, you should be able to see the 1 was updated. response. Going back to the article list, you will see the new title, and the Updated column will have a new value. CRUD – deleting data Deleting data is easier, since we don't need to do more than calling the built-in delete() method. Open the article manager, and add the following code: public function delete($id) { $article = Article::findFirstById($id); if (!$article) { throw new Exception('Article not found', 404); } if (false === $article->delete()) { foreach ($article->getMessages() as $message) { $error[] = (string) $message; } throw new Exception(json_encode($error)); } return true; } We will once again create a dummy method to delete records. Open modules/Backoffice/Controllers/ArticleControllers.php, and add the following code: public function deleteAction($id) { $this->view->disable(); $article_manager = $this->getDI()->get('core_article_manager'); try { $article_manager->delete($id); echo "Article was deleted."; } catch (Exception $e) { echo $e->getMessage(); } } To test this, simply access http://www.learning-phalcon.localhost/backoffice/article/delete/1. If everything went well, you should see the Article was deleted. message. Going back to, article list, you won't be able to see the article with ID 1 anymore. These are the four basic methods: create, read, update, and delete. Later in this book, we will use these methods a lot. If you need/want to, you can use the Phalcon Developer Tools to generate CRUD automatically. Check out https://github.com/phalcon/phalcon-devtools for more information. Using PHQL Personally, I am not a fan of PHQL. I prefer using ORM or Raw queries. But if you are going to feel comfortable with it, feel free to use it. PHQL is quite similar to writing raw SQL queries. The main difference is that you will need to pass a model instead of a table name, and use a models manager service or directly call the PhalconMvcModelQuery class. Here is a method similar to the built-in find() method: public function find() { $query = new PhalconMvcModelQuery("SELECT * FROM AppCoreModelsArticle", $this->getDI()); $articles = $query->execute(); return $articles; } To use the models manager, we need to inject this new service. Open the global services file, config/service.php, and add the following code: $di['modelsManager'] = function () { return new PhalconMvcModelManager(); }; Now let's rewrite the find() method by making use of the modelsManager service: public function find() { $query = $this->modelsManager->createQuery( "SELECT * FROM AppCoreModelsArticle"); $articles = $query->execute(); return $articles; } If we need to bind parameters, the method can look like this one: public function find() { $query = $this->modelsManager->createQuery( "SELECT * FROM AppCoreModelsArticle WHERE id = :id:"); $articles = $query->execute(array( 'id' => 2 )); return $articles; } We are not going to use PHQL at all in our project. If you are interested in it, you can find more information in the official documentation at http://docs.phalconphp.com/en/latest/reference/phql.html. Using raw SQL Sometimes, using raw SQL is the only way of performing complex queries. Let's see what a raw SQL will look like for a custom find() method and a custom update() method : <?php use PhalconMvcModelResultsetSimple as Resultset; class Article extends Base { public static function rawFind() { $sql = "SELECT * FROM robots WHERE id > 0"; $article = new self(); return new Resultset(null, $article, $article->getReadConnection()->query($sql)); } public static function rawUpdate() { $sql = "UPDATE article SET is_published = 1"; $this->getReadConnection()->execute($sql); } } As you can see, the rawFind() method returns an instance of PhalconMvcModelResultsetSimple. The rawUpdate() method just executes the query (in this example, we will mark all the articles as published). You might have noticed the getReadConnection() method. This method is very useful when you need to iterate over a large amount of data or if, for example, you use a master-slave connection. As an example, consider the following code snippet: <?php class Article extends Base { public function initialize() { $this->setReadConnectionService('a_slave_db_connection_service'); // By default is 'db' $this->setWriteConnectionService('db'); } } Working with models might be a complex thing. We cannot cover everything in this book, but we will work with many common techniques to achieve this part of our project. Please spare a little time and read more about working with models at http://docs.phalconphp.com/en/latest/reference/models.html. Database transactions If you need to perform multiple database operations, then in most cases you need to ensure that every operation is successful, for the sake of data integrity. A good database architecture in not always enough to solve potential integrity issues. This is the case where you should use transactions. Let's take as an example a virtual wallet that can be represented as shown in the next few tables. The User table looks like the following: ID NAME 1 John Doe The Wallet table looks like this: ID USER_ID BALANCE 1 1 5000 The Wallet transactions table looks like the following: ID WALLET_ID AMOUNT DESCRIPTION 1 1 5000 Bonus credit 2 1 -1800 Apple store How can we create a new user, credit their wallet, and then debit it as the result of a purchase action? This can be achieved in three ways using transactions: Manual transactions Implicit transactions Isolated transactions A manual transactions example Manual transactions are useful when we are using only one connection and the transactions are not very complex. For example, if any error occurs during an update operation, we can roll back the changes without affecting the data integrity: <?php class UserController extends PhalconMvcController { public function saveAction() { $this->db->begin(); $user = new User(); $user->name = "John Doe"; if (false === $user->save() { $this->db->rollback(); return; } $wallet = new Wallet(); $wallet->user_id = $user->id; $wallet->balance = 0; if (false === $wallet->save()) { $this->db->rollback(); return; } $walletTransaction = new WalletTransaction(); $walletTransaction->wallet_id = $wallet->id; $walletTransaction->amount = 5000; $walletTransaction->description = 'Bonus credit'; if (false === $walletTransaction1->save()) { $this->db->rollback(); return; } $walletTransaction1 = new WalletTransaction(); $walletTransaction1->wallet_id = $wallet->id; $walletTransaction1->amount = -1800; $walletTransaction1->description = 'Apple store'; if (false === $walletTransaction1->save()) { $this->db->rollback(); return; } $this->db->commit(); } } An implicit transactions example Implicit transactions are very useful when we need to perform operations on related tables / exiting relationships: <?php class UserController extends PhalconMvcController { public function saveAction() { $walletTransactions[0] = new WalletTransaction(); $walletTransactions[0]->wallet_id = $wallet->id; $walletTransactions[0]->amount = 5000; $walletTransactions[0]->description = 'Bonus credit'; $walletTransactions[1] = new WalletTransaction(); $walletTransactions[1]->wallet_id = $wallet->id; $walletTransactions[1]->amount = -1800; $walletTransactions[1]->description = 'Apple store'; $wallet = new Wallet(); $wallet->user_id = $user->id; $wallet->balance = 0; $wallet->transactions = $walletTransactions; $user = new User(); $user->name = "John Doe"; $user->wallet = $wallet; } } An isolated transactions example Isolated transactions are always executed in a separate connection, and they require a transaction manager: <?php use PhalconMvcModelTransactionManager as TxManager, PhalconMvcModelTransactionFailed as TxFailed; class UserController extends PhalconMvcController { public function saveAction() { try { $manager = new TxManager(); $transaction = $manager->get(); $user = new User(); $user->setTransaction($transaction); $user->name = "John Doe"; if ($user->save() == false) { $transaction->rollback("Cannot save user"); } $wallet = new Wallet(); $wallet->setTransaction($transaction); $wallet->user_id = $user->id; $wallet->balance = 0; if ($wallet->save() == false) { $transaction->rollback("Cannot save wallet"); } $walletTransaction = new WalletTransaction(); $walletTransaction->setTransaction($transaction);; $walletTransaction->wallet_id = $wallet->id; $walletTransaction->amount = 5000; $walletTransaction->description = 'Bonus credit'; if ($walletTransaction1->save() == false) { $transaction->rollback("Cannot create transaction"); } $walletTransaction1 = new WalletTransaction(); $walletTransaction1->setTransaction($transaction); $walletTransaction1->wallet_id = $wallet->id; $walletTransaction1->amount = -1800; $walletTransaction1->description = 'Apple store'; if ($walletTransaction1->save() == false) { $transaction->rollback("Cannot create transaction"); } $transaction->commit(); } catch(TxFailed $e) { echo "Error: ", $e->getMessage(); } } Summary In this article, you learned something about ORM in general and how to use some of the main built-in methods to perform CRUD operations. You also learned about database transactions and how to use PHQL or raw SQL queries. Resources for Article: Further resources on this subject: Using Phalcon Models, Views, and Controllers[article] Your first FuelPHP application in 7 easy steps[article] PHP Magic Features [article]
Read more
  • 0
  • 0
  • 4225

article-image-understanding-web-based-applications-and-other-multimedia-forms
Packt
20 Nov 2013
5 min read
Save for later

Understanding Web-based Applications and Other Multimedia Forms

Packt
20 Nov 2013
5 min read
(For more resources related to this topic, see here.) However, we will not look at blogs, wikis, or social networking sites that are usually referred to as web-based reference tools. Moodle already has these, so instead we will take a look at web applications that allows the easy creation, collaboration, and sharing of multimedia elements, such as interactive floor planners, online maps, timelines, and many others applications that are very easy to use, and that support different learning styles. Usually, I use Moodle as a school operating system and web apps as its social applications, to illustrate what I believe can be a very powerful way of using Moodle and the web for learning. Designing meaningful activities in Moodle gives students the opportunity to express their creativity by using these tools, and reflecting on the produced multimedia artifacts with both peers and teacher. However, we have to keep in mind some issues of e-safety, backups, and licensing when using these online tools, usually associated with online communities. After all, we will have our students using them, and they will therefore be exposed to some risks. Creating dynamic charts using Google Drive (Spreadsheets) Assigning students in our Moodle course tasks will require them to use a tool like Google Spreadsheets to present their plans to colleagues in a visual way. Google Drive (http://drive.google.com) provides a set of online productivity tools that work on web standards and recreates a typical Office suite. We can make documents, spreadsheets, presentations, drawings, or forms. To use Google Drive, we will need a Google account. After creating our account and logging in to Google Drive, we can organize the files displayed on the right side of the screen, add them to folders, tag them, search (of course, it's Google!), collaborate (imagine a wiki spreadsheet), export to several formats (including the usual formats for Office documents from Microsoft, Open Office, or Adobe PDF), and publish these documents online. We will start by creating a new Spreadsheet to make a budget for a music studio which will be built during the music course, by navigating to CREATE | Spreadsheet. Insert a chart As in any spreadsheet application, we can add a title by double-clicking on Untitled spreadsheet and then we add some equipment and cost to the cells: After populating our table with values and selecting all of them, we should click on the Insert chart button. The Start tab will show up in the Chart Editor pop up, as shown in the following screenshot: If we click on the Charts tab, we can pick from a list of available charts. Let's pick one of the pie charts. In the Customize tab, we can add a title to the chart, and change its appearance: When everything is done, we can click on the Insert button, and the chart previewed in the Customize tab will be added to the spreadsheet. Publish If we click on the chart, a square will be displayed on the upper-right corner, and if we click on the drop-down arrow, we see a Publish chart... option, which can be used to publish the chart. When we click on this option, we will be presented with two ways of embedding the chart, the first, as an interactive chart, and the second, as an image. Both change dynamically if we change the values or the chart in Google Drive. We should use the image code to put the chart on a Moodle forum. Share, comment, and collaborate Google Drive has the options of sharing and allowing comments and changes in our spreadsheet by other people. On the upper-right corner of each opened document, there are two buttons for that, Comments and Share. To add collaborators to our spreadsheet, we have to click on the Share button and then add their contacts (for example, e-mail) in the Invite people: field, then click on the Share & save button, and hit Done. If a collaborator is working on the same spreadsheet, at the same time we are, we can see it below the Comments and Share buttons as shown in the following screenshot: If we click on the arrow next to 1 other viewer we can chat directly with the collaborator as we edit it collaboratively: Remember that, this can be quite useful in distance courses that have collaborative tasks assigned to groups. Creating a shared folder using Google Drive We can also use the sharing functionality to share documents with the collaborators (15 GB of space for that). In the main Google Drive page, we can create a folder by navigating to Create | Folder. We are then required to give it a name: The folder will be shown in the files and folder explorer in Google Drive: To share it with someone, we need to right-click the folder and choose the Share... option. Then, just like the process of sharing a spreadsheet we saw previously, we just need to add our collaborators' contacts (for example, e-mail) in the Invite people: field, then click on Share & save and hit Done. The invited people will receive an e-mail to add the shared folder to their Google Drive (they need a Google account for this) and it is done. Everything we add to this folder is automatically synced with everyone. This includes all the Google Drive documents, PDFs, and all the files uploaded to this folder. And it's an easy way to share multimedia projects between a group of people working on the same project.
Read more
  • 0
  • 0
  • 4082

article-image-getting-started-leaflet
Packt
14 Jun 2013
9 min read
Save for later

Getting started with Leaflet

Packt
14 Jun 2013
9 min read
(For more resources related to this topic, see here.) Getting ready First, we need to get an Internet browser, if we don't have one already installed. Leaflet is tested with modern desktop browsers: Chrome, Firefox, Safari 5+, Opera 11.11+, and Internet Explorer 7-10. Internet Explorer 6 support is stated as not perfect but accessible. We can pick one of them, or all of them if we want to be thorough. Then, we need an editor. Editors come in many shapes and flavors: free or not free, with or without syntax highlighting, or remote file editing. A quick search on the Internet will provide thousands of capable editors. Notepad++ (http://notepad-plus-plus.org/) for Windows, Komodo Edit (http://www.activestate.com/komodo-edit) for Mac OS, or Vim (http://www.vim.org/) for Linux are among them. We can download Leaflet's latest stable release (v0.5.1 at the time of writing) and extract the content of the ZIP file somewhere appropriate. The ZIP file contains the sources as well as a prebuilt version of the library that can be found in the dist directory. Optionally, we can build from the sources included in the ZIP file; see this article's Building Leaflet from source section. Finally, let's create a new project directory on our hard drive and copy the dist folder from the extracted Leaflet package to it, ensuring we rename it to leaflet. How to do it... Note that the following code will constitute our code base throughout the rest of the article. Create a blank HTML file called index.html in the root of our project directory. Add the code given here and use the browser installed previously to execute it: <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="leaflet/ leaflet.css" /> <!--[if lte IE 8]> <link rel="stylesheet" type="text/css" href=" leaflet/ leaflet.ie.css" /> <![endif]--> <script src = "leaflet/leaflet.js"></script> <style> html, body, #map { height: 100%; } body { padding: 0; margin: 0; } </style> <title>Getting Started with Leaflet</title> </head> <body> <div id="map"></div> <script type="text/javascript"> var map = L.map('map', { center: [52.48626, -1.89042], zoom: 14 }); L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/ {x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); </script> </body> </html> The following screenshot is of the first map we have created: How it works... The index.html file we created is a standardized file that all Internet browsers can read and display the contents. Our file is based on the HTML doctype standard produced by the World Wide Web Consortium (W3C), which is only one of many that can be used as seen at http://www.w3.org/QA/2002/04/valid-dtd-list.html. Our index file specifies the doctype on the first line of code as required by the W3C, using the <!DOCTYPE HTML> markup. We added a link to Leaflet's main CSS file in the head section of our code: <link rel="stylesheet" type="text/css" href="leaflet/leaflet.css" /> We also added a conditional statement to link an Internet Explorer 8 or lower only stylesheet when these browsers interpret the HTML code: <!--[if lte IE 8]> <link rel="stylesheet" type="text/css" href="leaflet/leaflet.ie.css" /> <![endif]--> This stylesheet mainly addresses Internet Explorer specific issues with borders and margins. Leaflet's JavaScript file is then referred to using a script tag: <script src = "leaflet/leaflet.js"></script> We are using the compressed JavaScript file that is appropriate for production but very inefficient for debugging. In the compressed version, every white space character has been removed, as shown in the following bullet list, which is a straight copy-paste from the source of both files for the function onMouseClick: compressed: _onMouseClick:function(t){!this._loaded||this.dragging&& this.dragging.moved()||(this.fire("preclick"),this._ fireMouseEvent(t))}, uncompressed: _onMouseClick: function (e) { if (!this._loaded || (this.dragging && this.dragging.moved())) { return; } this.fire('preclick'); this._fireMouseEvent(e); }, To make things easier, we can replace leaflet.js with leaflet-src.js—an uncompressed version of the library. We also added styles to our document to make the map fit nicely in our browser window: html, body, #map { height: 100%; } body { padding: 0; margin: 0; } The <div> tag with the id attribute map in the document's body is the container of our map. It must be given a height otherwise the map won't be displayed: <div id="map" style="height: 100%;" ></div> Finally, we added a script section enclosing the map's initialization code, instantiating a Map object using the L.map(…) constructor and a TileLayer object using the L.tileLayer(…) constructor. The script section must be placed after the map container declaration otherwise Leaflet will be referencing an element that does not yet exist when the page loads. When instantiating a Map object, we pass the id of the container of our map and an array of Map options: var map = L.map('map', { center: [52.48626, -1.89042], zoom: 14 }); There are a number of Map options affecting the state, the interactions, the navigation, and the controls of the map. See the documentation to explore those in detail at http://leafletjs.com/reference.html#map-options. Next, we instantiated a TileLayer object using the L.tileLayer(…) constructor and added to the map using the TileLayer.addTo(…) method: L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); Here, the first parameter is the URL template of our tile provider—that is OpenStreetMap— and the second a noncompulsory array of TileLayer options including the recommended attribution text for our map tile's source. The TileLayer options are also numerous. Refer to the documentation for the exhaustive list at http://leafletjs.com/reference.html#tilelayer-options. There's more... Let's have a look at some of the Map options, as well as how to build Leaflet from source or use different tile providers. More on Map options We have encountered a few Map options in the code for this recipe, namely center and zoom. We could have instantiated our OpenStreetMap TileLayer object before our Map object and passed it as a Map option using the layers option. We also could have specified a minimum and maximum zoom or bounds to our map, using minZoom and maxZoom (integers) and maxBounds, respectively. The latter must be an instance of LatLngBounds: var bounds = L.latLngBounds([ L.latLng([52.312, -2.186]), L.latLng([52.663, -1.594]) ]); We also came across the TileLayer URL template that will be used to fetch the tile images, replacing { s} by a subdomain and { x}, {y}, and {z} by the tiles coordinate and zoom. The subdomains can be configured by setting the subdomains property of a TileLayer object instance. Finally, the attribution property was set to display the owner of the copyright of the data and/or a description. Building Leaflet from source A Leaflet release comes with the source code that we can build using Node.js. This will be a necessity if we want to fix annoying bugs or add awesome new features. The source code itself can be found in the src directory of the extracted release ZIP file. Feel free to explore and look at how things get done within a Leaflet. First things first, go to http://nodejs.org and get the install file for your platform. It will install Node.js along with npm, a command line utility that will download and install Node Packaged Modules and resolve their dependencies for us. Following is the list of modules we are going to install: Jake: A JavaScript build program similar to make JSHint: It will detect potential problems and errors in JavaScript code UglifyJS: A mangler and compressor library for JavaScript Hopefully, we won't need to delve into the specifics of these tools to build Leaflet from source. So let's open a command line interpreter— cmd.exe on Windows, or a terminal on Mac OSX or Linux—and navigate to the Leaflet's src directory using the cd command, then use npm to install Jake, JSHint and UglifyJS: cd leaflet/src npm install –g jake npm install jshint npm install uglify-js We can now run Jake in Leaflet's directory: jake What about tile providers? We could have chosen a different tile provider as OpenStreetMap is free of charge but has its limitations in regard of a production environment. A number of web services provide tiles but might come at a price depending on your usage: CloudMade, MapQuest. These three providers serve tiles use the OpenStreetMap tile scheme described at http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames. Remember the way we added the OpenStreetMap layer to the map? L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); Remember the way we added the OpenStreetMap layer to the map? Cloudmade: L.tileLayer(' http://{s}.tile.cloudmade.com/API-key/997/256/{z}/ {x}/{y}.png', { attribution: ' Map data © <a href="http://openstreetmap. org">OpenStreetMap</a> contributors, <a href="http:// creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>' }).addTo(map); MapQuest: L.tileLayer('http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}. png', { attribution: ' Tiles Courtesy of <a href="http://www.mapquest. com/" target="_blank">MapQuest</a> <img src = "http://developer.mapquest.com/content/osm/mq_logo.png">', subdomains: ['otile1', 'otile2', 'otile3', 'otile4'] }).addTo(map); You will learn more about the Layer URL template and subdomains option in the documentation at http://leafletjs.com/reference.html#tilelayer. Leaflet also supports Web Map Service (WMS) tile layers—read more about it at http://leafletjs.com/reference.html#tilelayer-wms—and GeoJSON layers in the documentation at http://leafletjs.com/reference.html#geojson. Summary In this article we have learned how to create map using Leaflet and created our first map. We learned about different map options and also how to build a leaflet from source. Resources for Article : Further resources on this subject: Using JavaScript Effects with Joomla! [Article] Getting Started with OpenStreetMap [Article] Quick start [Article]
Read more
  • 0
  • 0
  • 4041

article-image-creating-camel-project-simple
Packt
27 Aug 2013
8 min read
Save for later

Creating a Camel project (Simple)

Packt
27 Aug 2013
8 min read
(For more resources related to this topic, see here.) Getting ready For the examples in this article, we are going to use Apache Camel version 2.11 (http://maven.apache.org/) and Apache Maven version 2.2.1 or newer (http://maven.apache.org/) as a build tool. Both of these projects can be downloaded for free from their websites. The complete source code for all the examples in this article is available on github at https://github.com/bibryam/camel-message-routing-examples repository. It contains Camel routes in Spring XML and Java DSL with accompanying unit tests. The source code for this tutorial is located under the project: camel-message-routing-examples/creating-camel-project. How to do it... In a new Maven project add the following Camel dependency to the pom.xml: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>${camel-version}</version></dependency> With this dependency in place, creating our first route requires only a couple of lines of Java code: public class MoveFileRoute extends RouteBuilder { @Override public void configure() throws Exception { from("file://source") .to("log://org.apache.camel.howto?showAll=true") .to("file://target"); }} Once the route is defined, the next step is to add it to CamelContext, which is the actual routing engine and run it as a standalone Java application: public class Main { public static void main(String[] args) throws Exception { CamelContext camelContext = new DefaultCamelContext(); camelContext.addRoutes(new MoveFileRoute()); camelContext.start(); Thread.sleep(10000); camelContext.stop(); }} That's all it takes to create our first Camel application. Now, we can run it using a Java IDE or from the command line with Maven mvn exec:java. How it works... Camel has a modular architecture; its core (camel-core dependency) contains all the functionality needed to run a Camel application—DSL for various languages, the routing engine, implementations of EIPs, a number of data converters, and core components. This is the only dependency needed to run this application. Then there are optional technology specific connector dependencies (called components) such as JMS, SOAP, JDBC, Twitter, and so on, which are not needed for this example, as the file and log components we used are all part of the camel-core. Camel routes are created using a Domain Specific Language (DSL), specifically tailored for application integration. Camel DSLs are high-level languages that allow us to easily create routes, combining various processing steps and EIPs without going into low-level implementation details. In the Java DSL, we create a route by extending RouteBuilder and overriding the configure method. A route represents a chain of processing steps applied to a message based on some rules. The route has a beginning defined by the from endpoint, and one or more processing steps commonly called "Processors" (which implement the Processor interface). Most of these ideas and concepts originate from the Pipes and Filters pattern from the Enterprise Integration Patterns articlee by Gregor Hohpe and Bobby Woolf. The article provides an extensive list of patterns, which are also available at http://www.enterpriseintegrationpatterns.com, and the majority of which are implemented by Camel. With the Pipes and Filters pattern, a large processing task is divided into a sequence of smaller independent processing steps (Filters) that are connected by channels (Pipes). Each filter processes messages received from the inbound channel, and publishes the result to the outbound channel. In our route, the processing steps are reading the file using a polling consumer, logging it and writing the file to the target folder, all of them piped by Camel in the sequence specified in the DSL. We can visualize the individual steps in the application with the following diagram: A route has exactly one input called consumer and identified by the keyword from. A consumer receives messages from producers or external systems, wraps them in a Camel specific format called Exchange , and starts routing them. There are two types of consumers: a polling consumer that fetches messages periodically (for example, reading files from a folder) and an event-driven consumer that listens for events and gets activated when a message arrives (for example, an HTTP server). All the other processor nodes in the route are either a type of integration pattern or producers used for sending messages to various endpoints. Producers are identified by the keyword to and they are capable of converting exchanges and delivering them to other channels using the underlying transport mechanism. In our example, the log producer logs the files using the log4J API, whereas the file producer writes them to a target folder. The route is not enough to have a running application; it is only a template that defines the processing steps. The engine that runs and manages the routes is called Camel Context. A high level view of CamelContext looks like the following diagram: CamelContext is a dynamic multithread route container, responsible for managing all aspects of the routing: route lifecycle, message conversions, configurations, error handling, monitoring, and so on. When CamelContext is started, it starts the components, endpoints and activates the routes. The routes are kept running until CamelContext is stopped again when it performs a graceful shutdown giving time for all the in-flight messages to complete processing. CamelContext is dynamic, it allows us to start, stop routes, add new routes, or remove running routes at runtime. In our example, after adding the MoveFileRoute, we start CamelContext and let it copy files for 10 seconds, and then the application terminates. If we check the target folder, we should see files copied from the source folder. There's more... Camel applications can run as standalone applications or can be embedded in other containers such as Spring or Apache Karaf. To make development and deployment to various environments easy, Camel provides a number of DSLs, including Spring XML, Blueprint XML, Groovy, and Scala. Next, we will have a look at the Spring XML DSL. Using Spring XML DSL Java and Spring XML are the two most popular DSLs in Camel. Both provide access to all Camel features and the choice is mostly a matter of taste. Java DSL is more flexible and requires fewer lines of code, but can easily become complicated and harder to understand with the use of anonymous inner classes and other Java constructs. Spring XML DSL, on the other hand, is easier to read and maintain, but it is too verbose and testing it requires a little more effort. My rule of thumb is to use Spring XML DSL only when Camel is going to be part of a Spring application (to benefit from other Spring features available in Camel), or when the routing logic has to be easily understood by many people. For the routing examples in the article, we are going to show a mixture of Java and Spring XML DSL, but the source code accompanying this article has all the examples in both DSLs. In order to use Spring, we also need the following dependency in our projects: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring</artifactId> <version>${camel-version}</version></dependency> The same application for copying files, written in Spring XML DSL looks like the following: <beans xsi_schemaLocation=" http ://www.springframework.org/schema/beans http ://www.springframework.org/schema/beans/spring-beans.xsd http ://camel.apache.org/schema/spring http ://camel.apache.org/schema/spring/camel-spring.xsd"><camelContext > <route> <from uri="file://source"/> <to uri="log://org.apache.camel.howto?showAll=true"/> <to uri="file://target"/> </route></camelContext></beans> Notice that this is a standard Spring XML file with an additional CamelContext element containing the route. We can launch the Spring application as part of a web application, OSGI bundle, or as a standalone application: public static void main(String[] args) throws Exception { AbstractApplicationContext springContext = new ClassPathXmlApplicationContext("META-INF/spring/move-file-context.xml"); springContext.start(); Thread.sleep(10000); springContext.stop();} When the Spring container starts, it will instantiate a CamelContext, start it and add the routes without any other code required. That is the complete application written in Spring XML DSL. More information about Spring support in Apache Camel can be found at http://camel.apache.org/spring.html. Summary This article provides a high-level overview of Camel architecture, and demonstrates how to create a simple message driven application. Resources for Article: Further resources on this subject: Binding Web Services in ESB—Web Services Gateway [Article] Drools Integration Modules: Spring Framework and Apache Camel [Article] Routing to an external ActiveMQ broker [Article]
Read more
  • 0
  • 0
  • 3956

article-image-learning-nservicebus-preparing-failure
Packt
09 Feb 2015
19 min read
Save for later

Learning NServiceBus - Preparing for Failure

Packt
09 Feb 2015
19 min read
 In this article by David Boike, author of the book Learning NServiceBus Second Edition we will explore the tools that NServiceBus gives us to stare at failure in the face and laugh. We'll discuss error queues, automatic retries, and controlling how those retries occur. We'll also discuss how to deal with messages that may be transient and should not be retried in certain conditions. Lastly, we'll examine the difficulty of web service integrations that do not handle retries cleanly on their own. (For more resources related to this topic, see here.) Fault tolerance and transactional processing In order to understand the fault tolerance we gain from using NServiceBus, let's first consider what happens without it. Let's order something from a fictional website and watch what might happen to process that order. On our fictional website, we add Batman Begins to our shopping cart and then click on the Checkout button. While our cursor is spinning, the following process is happening: Our web request is transmitted to the web server. The web application knows it needs to make several database calls, so it creates a new transaction scope. Database Call 1 of 3: The shopping cart information is retrieved from the database. Database Call 2 of 3: An Order record is inserted. Database Call 3 of 3: We attempt to insert OrderLine records, but instead get Error Message: Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. This exception causes the transaction to roll back. This process is shown in the following diagram:   Ugh! If you're using SQL Server and you've never seen this, you haven't been coding long enough. It never happens during development; there just isn't enough load. It's even possible that this won't occur during load testing. It will likely occur during heavy load at the worst possible time, for example, right after your big launch. So obviously, we should log the error, right? But then what happens to the order? Well that's gone, and your boss may not be happy about losing that revenue. And what about our user? They will likely get a nasty error message. We won't want to divulge the actual exception message, so they will get something like, "An unknown error has occurred. The system administrator has been notified. Please try again later." However, the likelihood that they want to trust their credit card information to a website that has already blown up in their face once is quite low. So how can we do better? Here's how this scenario could have happened with NServiceBus:   The web request is transmitted to the web server. We add the shopping cart identifier to an NServiceBus command and send it through the Bus. We redirect the user to a new page that displays the receipt, even though the order has not yet been processed. Elsewhere, an Order service is ready to start processing a new message: The service creates a new transaction scope, and receives the message within the transaction. Database Call 1 of 3: The shopping cart information is retrieved from the database. Database Call 2 of 3: An Order record is inserted. Database Call 3 of 3: Deadlock! The exception causes the database transaction to roll back. The transaction controlling the message also rolls back. The order is back in the queue. This is great news! The message is back in the queue, and by default, NServiceBus will automatically retry this message a few times. Generally, deadlocks are a temporary condition, and simply trying again is all that is needed. After all, the SQL Server exception says Rerun the transaction. Meanwhile, the user has no idea that there was ever a problem. It will just take a little longer (in the order of milliseconds or seconds) to process the order. Error queues and replay Whenever you talk about automatic retries in a messaging environment, you must invariably consider poison messages. A poison message is a message that cannot be immediately resolved by a retry because it will consistently result in an error. A deadlock is a transient error. We can reasonably expect deadlocks and other transient errors to resolve by themselves without any intervention. Poison messages, on the other hand, cannot resolve themselves. Sometimes, this is because of an extended outage. At other times, it is purely our fault—an exception we didn't catch or an input condition we didn't foresee. Automatic retries If we retry poison messages in perpetuity, they will create a blockage in our incoming queue of messages. They will retry over and over, and valid messages will get stuck behind them, unable to make it through. For this reason, we must set a reasonable limit on retries, and after failing too many times, poison messages must be removed from the processing queue and stored someplace else. NServiceBus handles all of this for us. By default, NServiceBus will try to process a message five times, after which it will move the message to an error queue, configured by the MessageForwardingInCaseOfFaultConfig configuration section: <MessageForwardingInCaseOfFaultConfigErrorQueue="error" /> It is in this error queue that messages will wait for administrative intervention. In fact, you can even specify a different server to collect these messages, which allows you to configure one central point in a system where you watch for and deal with all failures: <MessageForwardingInCaseOfFaultConfigErrorQueue="error@SERVER" /> As mentioned previously, five failed attempts form the default metric for a failed message, but this is configurable via the TransportConfig configuration section: <section name="TransportConfig" type="NServiceBus.Config.TransportConfig, NServiceBus.Core" /> ... <TransportConfig MaxRetries="3" /> You could also generate the TransportConfig section using the Add-NServiceBusTransportConfig PowerShell cmdlet. Keep two things in mind: Depending upon how you read it, MaxRetries can be a somewhat confusing name. What it really means is the total number of tries, so a value of 5 will result in the initial attempt plus 4 retries. This has the odd side effect that MaxRetries="0" is the same as MaxRetries="1". In both instances, the message would be attempted once. During development, you may want to limit retries to MaxRetries="1" so that a single error doesn't cause a nausea-inducing wall of red that flushes your console window's buffer, leaving you unable to scroll up to see what came before. You can then enable retries in production by deploying the endpoint with a different configuration. Replaying errors What happens to those messages unlucky enough to fail so many times that they are unceremoniously dumped in an error queue? "I thought you said that Alfred would never give up on us!" you cry. As it turns out, this is just a temporary holding pattern that enables the rest of the system to continue functioning, while the errant messages await some sort of intervention, which can be human or automated based on your own business rules. Let's say our message handler divides two numbers from the incoming message, and we forget to account for the possibility that one of those numbers might be zero and that dividing by zero is frowned upon. At this point, we need to fix the error somehow. Exactly what we do will depend upon your business requirements: If the messages were sent in an error, we can fix the code that was sending them. In this case, the messages in the error queue are junk and can be discarded. We can check the inputs on the message handler, detect the divide-by-zero condition, and make compensating actions. This may mean returning from the message handler, effectively discarding any divide-by-zero messages that are processed, or it may mean doing new work or sending new messages. In this case, we may want to replay the error messages after we have deployed the new code. We may want to fix both the sending and receiving side. Second-level retries Automatically retrying error messages and sending repeated errors to an error queue is a pretty good strategy to manage both transient errors, such as deadlocks, and poison messages, such as an unrecoverable exception. However, as it turns out, there is a gray area in between, which is best referred to as semi-transient errors. These include incidents such as a web service being down for a few seconds, or a database being temporarily offline. Even with a SQL Server failover cluster, the failover procedure can take upwards of a minute depending on its size and traffic levels. During a time like this, the automatic retries will be executed immediately and great hordes of messages might go to the error queue, requiring an administrator to take notice and return them to their source queues. But is this really necessary? As it turns out, it is not. NServiceBus contains a feature called Second-Level Retries (SLR) that will add additional sets of retries after a wait. By default, the SLR will add three additional retry sessions, with an additional wait of 10 seconds each time. By contrast, the original set of retries is commonly referred to as First-Level Retries (FLR). Let's track a message's full path to complete failure, assuming default settings: Attempt to process the message five times, then wait for 10 seconds Attempt to process the message five times, then wait for 20 seconds Attempt to process the message five times, then wait for 30 seconds Attempt to process the message five times, and then send the message to the error queue Remember that by using five retries, NServiceBus attempts to process the message five times on every pass. Using second-level retries, almost every message should be able to be processed unless it is definitely a poison message that can never be successfully processed. Be warned, however, that using SLR has its downsides too. The first is ignorance of transient errors. If an error never makes it to an error queue and we never manually check out the error logs, there's a chance we might miss it completely. For this reason, it is smart to always keep an eye on error logs. A random deadlock now and then is not a big deal, but if they happen all the time, it is probably still worth some work to improve the code so that the deadlock is not as frequent. An additional risk lies in the time to process a true poison message through all the retry levels. Not accounting for any time taken to process the message itself 20 times or to wait for other messages in the queue, the use of second-level retries with the default settings results in an entire minute of waiting before you see the message in an error queue. If your business stakeholders require the message to either succeed or fail in 30 seconds, then you cannot possibly meet those requirements. Due to the asynchronous nature of messaging, we should be careful never to assume that messages in a distributed system will arrive in any particular order. However, it is still good to note that the concept of retries exacerbates this problem. If Message A and then Message B are sent in order, and Message B succeeds immediately but Message A has to wait in an error queue for awhile, then they will most certainly be processed out of order. Luckily, second-level retries are completely configurable. The configuration element is shown here with the default settings: <section name="SecondLevelRetriesConfig" type="NServiceBus.Config.SecondLevelRetriesConfig,   NServiceBus.Core"/> ... <SecondLevelRetriesConfig Enabled="true"                          TimeIncrease="00:00:10"                          NumberOfRetries="3" /> You could also generate the SecondLevelRetriesConfig section using the Add-NServiceBus SecondLevelRetriesConfig PowerShell cmdlet. Keep in mind that you may want to disable second-level retries, like first-level retries, during development for convenience, and then enable them in production. Messages that expire Messages that lose their business value after a specific amount of time are an important consideration with respect to potential failures. Consider a weather reporting system that reports the current temperature every few minutes. How long is that data meaningful? Nobody seems to care what the temperature was 2 hours ago; they want to know what the temperature is now! NServiceBus provides a method to cause messages to automatically expire after a given amount of time. Unlike storing this information in a database, you don't have to run any batch jobs or take any other administrative action to ensure that old data is discarded. You simply mark the message with an expiration date and when that time arrives, the message simply evaporates into thin air: [TimeToBeReceived("01:00:00")] public class RecordCurrentTemperatureCmd : ICommand { public double Temperature { get; set; } } This example shows that the message must be received within one hour of being sent, or it is simply deleted by the queuing system. NServiceBus isn't actually involved in the deletion at all, it simply tells the queuing system how long to allow the message to live. If a message fails, however, and arrives at an error queue, NServiceBus will not include the expiration date in order to give you a chance to debug the problem. It would be very confusing to try to find an error message that had disappeared into thin air! Another valuable use for this attribute is for high-volume message types, where a communication failure between servers or extended downtime could cause a huge backlog of messages to pile up either at the sending or the receiving side. Running out of disk space to store messages is a show-stopper for most message-queuing systems, and the TimeToBeReceived attribute is the way to guard against it. However, this means we are throwing away data, so we need to be very careful when applying this strategy. It should not simply be used as a reaction to low disk space! Auditing messages At times, it can be difficult to debug a distributed system. Commands and events are sent all around, but after they are processed, they go away. We may be able to tell what will happen to a system in the future by examining queued messages, but how can we analyze what happened in the past? For this reason, NServiceBus contains an auditing function that will enable an endpoint to send a copy of every message it successfully processes to a secondary location, a queue that is generally hosted on a separate server. This is accomplished by adding an attribute or two to the UnicastBusConfig section of an endpoint's configuration: <UnicastBusConfig ForwardReceivedMessagesTo="audit@SecondaryServer" TimeToBeReceivedOnForwardedMessages="1.00:00:00"> <MessageEndpointMappings>    <!-- Mappings go here --> </MessageEndpointMappings> </UnicastBusConfig> In this example, the endpoint will forward a copy of all successfully processed messages to a queue named audit on a server named SecondaryServer, and those messages will expire after one day. While it is not required to use the TimeToBeReceivedOnForwardedMessages parameter, it is highly recommended. Otherwise, it is possible (even likely) that messages will build up in your audit queue until you run out of available storage, which you would really like to avoid. The exact time limit you use is dependent upon the volume of messages in your system and how much storage your queuing system has available. You don't even have to design your own tool to monitor these audit messages; the Particular Service Platform has that job covered for you. NServiceBus includes the auditing configuration in new endpoints by default so that ServiceControl, ServiceInsight, and ServicePulse can keep tabs on your system. Web service integration and idempotence When talking about managing failure, it's important to spend a few minutes discussing web services because they are such a special case; they are just too good at failing. When the message is processed, the email would either be sent or it won't; there really aren't any in-between cases. In reality, when sending an email, it is technically possible that we could call the SMTP server, successfully send an email, and then the server could fail before we are able to finish marking the message as processed. However, in practice, this chance is so infinitesimal that we generally assume it to be zero. Even if it is not zero, we can assume in most cases that sending a user a duplicate email one time in a few million won't be the end of the world. Web services are another story. There are just so many ways a web service can fail: A DNS or network failure may not let us contact the remote web server at all The server may receive our request, but then throw an error before any state is modified on the server The server may receive our request and successfully process it, but a communication problem prevents us from receiving the 200 OK response The connection times out, thus ignoring any response the server may have been about to send us For this reason, it makes our lives a lot easier if all the web services we ever have to deal with are idempotent, which means a process that can be invoked multiple times with no adverse effects. Any service that queries data without modifying it is inherently idempotent. We don't have to worry about how many times we call a service if doing so doesn't change any data. Where we start to get into trouble is when we begin mutating state. Sometimes, we can modify state safely. Consider an example used previously regarding registering for alert notifications. Let's assume that on the first try, the third-party service technically succeeds in registering our user for alerts, but it takes too long to do so and we receive a timeout error. When we retry, we ask to subscribe the email address to alerts again, and the web service call succeeds. What's the net effect? Either way, the user is subscribed for alerts. This web service satisfies idempotence. The classic example of a non-idempotent web service is a credit card transaction processor. If the first attempt to authorize a credit card succeeds on the server and we retry, we may double charge our customer! This is not an acceptable business case and you will quickly find many people angry with you. In these cases, we need to do a little work ourselves because unfortunately, it's impossible for NServiceBus to know whether your web service is idempotent or not. Generally, this work takes the form of recording each step we perform on durable storage in real time, and then query that storage to see which steps have been attempted. In our example of credit card processing, the happy path approach would look like this: Record our intent to make a web service call to durable storage. Make the actual web service call. Record the results of the web service call to durable storage. Send commands or publish events with the results of the web service call. Now, if the message is retried, we can inspect the durable storage and decide what step to jump to and whether any compensating actions need to be taken first. If we have recorded our intent to call the web service but do not see any evidence of a response, we can query the credit card processor based on an order or transaction identifier. Then we will know whether we need to retry the authorization or just get the results of the already completed authorization. If we see that we have already made the web service call and received the results, then we know that the web service call was successful but some exception happened before the resulting messages could be sent. In response, we can just take the results and send the messages without requiring any further web service invocations. It's important to be able to handle the case where our durable storage throws an exception, rendering us unable to make our state persist. This is why it's so important to record the intent to do something before attempting it—so that we know the difference between never having done something and attempting it but not necessarily knowing the results. The process we have just discussed is admittedly a bit abstract, and can be visualized much more easily with the help of the following diagram:   The choice of using the durable storage strategy for this process is up to you. If you choose to use a database, however, you must remember to exempt it from the message handler's ambient transaction, or those changes will also get rolled back if and when the handler fails. In order to escape the transaction to write to durable storage, use a new TransactionScope object to suppress the transaction, like this: public void Handle(CallNonIdempotentWebServiceCmdcmd) { // Under control of ambient transaction   using (var ts = new TransactionScope(TransactionScopeOption.Suppress)) {    // Not under transaction control    // Write updates to durable storage here    ts.Complete(); }   // Back under control of ambient transaction } Summary In this article, we considered the inevitable failure of our software and how NServiceBus can help us to be prepared for it. You learned how NServiceBus promises fault tolerance within every message handler so that messages are never dropped or forgotten, but instead retried and then held in an error queue if they cannot be successfully processed. Once we fix the error, or take some other administrative action, we can replay those messages. In order to avoid flooding our system with useless messages during a failure, you learned how to cause messages that lose their business value after a specific amount of time to expire. Finally, you learned how to build auditing in a system by forwarding a copy of all messages for later inspection, and how to properly deal with the challenges involved in calling external web services. In this article, we dealt exclusively with NServiceBus endpoints hosted by the NServiceBus Host process.
Read more
  • 0
  • 0
  • 3939

article-image-using-moodle-integrate-foreign-language-course-secondary-school
Guest Contributor
18 Mar 2010
11 min read
Save for later

Using Moodle to integrate a Foreign Language Course in Secondary School

Guest Contributor
18 Mar 2010
11 min read
This article is written by Mariella Proietta. Introduction: technology and the learning process Researchers and practitioners, both agree on the essential role played by technology in the learning process. Yet the discussion on the changes brought about by the adoption of ICT is still controversial. An emerging topic is the importance of technology in motivating students. Academic motivation is a critical need to address, especially in high school education, since motivational features change and can significantly influence the engagement, learning, achievement, and future aspirations and intentions of students (Deci and Ryan 1985; Hardré and Reeve 2003; Pintrich and Schunk 1996). Motivation is a result of interaction between external and internal factors. It depends on individual differences, influence of outside experiences, and from interactions with teachers and peers in school. Different studies have shown the use of technological tools to increase motivation and Computer Assisted Learning (CAL) has been encouraged and developed in every field. The use of Computer Assisted Language Learning (CALL) has produced a great deal of literature from perspectives such as cognitive psychology, constructivism, psycholinguistics and has undertaken different phases from behaviouristic to integrative or integrated. Bax (2003) talks about approaches from restricted CALL, open CALL to integrated CALL. He describes them concluding that teachers’ aim should be to attain a state of 'normalisation' in which the technology is invisible and truly integrated. The expectation that teachers would adopt ICT and change their practices in particular ways has been recently questioned by research which indicates that teachers have not changed in the ways expected and researchers try to understand why. J. Orlando(2009) explores the existing literature on the matter stating that effective practices include frequency of use for knowledge construction, using ICT to enhance teaching efficiency and to extend and transform learning teachers’ practices. She notes that there is a common assumption that teachers move along and complete a determined path of change caused by the ‘techno-centric’ expectation of immediacy of change in their practices as a result of the use of ICT. She proposes a different design considering research as an evolving process, fashioned over the course of the study. This change may produce new data. But the change with ICT is distinctive and complex mainly because ICT resource innovations are continuously and rapidly changing. A new perspective helps to understand how and why changes in teaching practices mediated by ICT occur and contribute to understand the phenomenon of ICT and the impact it is having on teaching practices. Improvement and integration of the learning process in foreign language teaching Recent studies explore the increasing role of educational activities outside the classroom in the teaching and learning of foreign languages by means of hybrid learning arrangements and the integration of e-learning with classical classroom instruction. Bärenfänger (2005) explores the studies on the subject and introduces the elements of resulting pedagogic arrangements such as online references, asynchronous web-based learning, email, online assessment and testing, mentoring and tutoring. The study includes portals, synchronous web-based learning, electronic performance support systems, simulations, knowledge management, self-paced CD-ROM based content, communities of practice, video broadcasts, virtual labs and chat rooms. The author notes that these new tools satisfy the needs of learners, improve the quality of the learning experience, decrease the time a learner needs to achieve a learning goal, improve quality of the learning content and materials, improve re-usability of the learning content and materials. Among the advantages these tools also reduce cost of program delivery, allow a more effective map learning components to objectives and reduce cost of program development. Other studies have shown that distant or blended courses do not interfere with oral proficiency and interaction. According to Blake and others ‘many teachers still harbour deep-seated doubts as to whether or not a hybrid course, much less a completely distance-learning class, could provide L2 learners with a way to reach linguistic proficiency, especially with respect to oral language skills’ (Blake et al., 2008). In their study, they show that classroom, hybrid, and distance L2 learners reach comparable levels of oral proficiency during their first year of study. The Italian context In most Italian secondary schools the language course takes place mainly in the classroom (often three hours a week) with students having the opportunity to practice the four skills in a more conventional way. Some schools offer additional hours in which students are asked to work in the school multimedia laboratory, and integrate their language abilities with ICT. The majority of Italian secondary school students have, at home, a personal computer and an easy access to the web, but most of their time is spent chatting in their mother tongue and using a social network. When they are asked to visit foreign websites, find information in English or other foreign languages, do online language practice or similar activities, only a few of them are capable to accomplish the task, while the remaining students want to do the activities at school under the supervision of the teacher. The result is that most of the time is spent doing, at schools, activities that could be easily done at home. Moreover, very few students write and speak in English to communicate, apart from the simulations during the lesson, and their listening practice is mainly with songs. The procedure planned here tries to solve these problems and aims to improve and integrate the learning process with online activities. Using the platform Moodle to integrate the textbook Second language teachers can find a help to create engaging online language learning activities using the Moodle platform in different web sites, and a recent book has been written by J. Stanford for teachers, trainers, and course planners, with little or no experience of Moodle, who want to create their own language learning activities (Stanford 2009). It offers plenty of suggestions and examples for adapting classroom activities to the virtual learning environment and the author has also created a demo site http://moodleforlanguages.co.uk). What we are trying here is slightly different: we try to use the platform Moodle to support and integrate conventional class language activities. Creating learning tasks with Moodle The tools provided by Moodle can be used to integrate any level course, provide additional work outside the class and experience cooperative learning. According to Brandl ‘as a courseware package and learning System, Moodle has great potential for supporting conventional classroom instruction, for example, to do additional work outside of class, to become the delivery System for blended (or hybrid) course formats, or even to be used as a standalone e-learning platform’ (Brandl, 2005). Moodle and its platform can thus be used to integrate the school course, inviting the students to join the modules and try the new experience. They can be asked by the teacher to attend the platform and receive credits or marks, which will contribute to the end-of-year evaluation. The result of this kind of experience may contribute to support the use of new technologies in secondary schools, and increase foreign language proficiency. Preparing the platform Teachers or instructors should first prepare the platform and its parts before starting the activities, caring that each language skill could be exploited, and then they could invite their students to join the integration course. As regards language learning, among the different features, the quiz-making function has been analysed and used by many instructors and authors. Robb states that Moodle's functions ‘allow you to make different types of quizzes. Quiz types relevant to language teaching are: Multiple choice, True/False, Numerical, Matching, Description, and Cloze. A wide range of options allows you to randomize the questions and multiple-choice items, specify a time frame for availability, choose whether the students receive feedback or not, decide if they are allowed to view the correct answers, and determine how many times they may take the quiz and how it is to be scored (first attempt, highest attempt, average of all attempts or last attempt)’ (Robb, 2004). Planning the procedure Since the intention is not to substitute the textbooks, CDs or CD ROM, but to integrate them with an e-learning environment, the following steps may be followed, to create the module or sections in the platform and provide the interaction needed: The teacher chooses some Units of the textbook (or textbooks) that can be more easily considered as Learning Objects (modular digital resources that are uniquely identified and can be used and reused to support learning. The main idea of 'learning objects' is that educational content is broken down into small chunks that can be reused in various learning environments). Some of the audio material (tracks) on CDs can be saved as audio files in a directory to be used as a resource. Short video sequences can offer dialogues corresponding to the units chosen. Many sites such as the site of the BBC http://www.bbc.co.uk/worldservice/learningenglish and other sites ( e.g. http://www.lingual.net/lingualproductitems/details.php) provide this sort of video material that can be linked or downloaded from the platform. Additional audio material should be prepared, such as listening exercises, whose solutions and answers could be sent via e-mail to the teacher for correction or recorded by the students and put in an area of the platform where other students could access for listening and discussion in a chat room. A particular section of Moodle offers the opportunity to create quizzes of different kinds. Instructors and teachers who are familiar with ‘Macromedia Flash’ or similar programs can also produce interactive web pages with exercises such as drag and drop or true or false. Otherwise, each section could have some links to web sites with plenty of exercises. The teacher has only to take care that there is a great deal of interaction and feedback. Evaluation may be done through different kinds of tests. At the end of each test a mark or score can be given to each student, and added to the general evaluation in the subject. An additional mark may be given to the frequency with which students attend the platform and the areas in which they can swap information. To illustrate the procedure we have created a module choosing some of the contents of Horizons Options pre­intermediate used in Italian secondary schools mostly in the second or third year. The first approach, after the login and the choice of course, may be with a chart similar to figure 1 that can be put in the main frame: The access to each Section can be done either independently or in sequence in the sense that Section 2 can be opened only after having done the main activities in Section 1. The ‘i’ on the right provides general information about the content of the Section. By clicking on one of the titles of the sections, e.g. Clothes and fashion you can open either a frame or a new window similar to the following (figure 2): The exercises provided are mostly interactive and they can be scored independently. A particular area of the platform may be used as a kind of forum where the students write their doubts and the teacher gives explanation. They can also be encouraged to suggest the solution to the questions asked by others. Another area may be used to chat freely in the foreign language. To avoid the unbalance between oral and written skills, particular care should be taken in using tools that allow the recording of the voice and the oral communication. Students could be asked to telephone and record their call or interview a friend and put the recording on the platform. Conclusion The ideas provided in this article are only the starting point for the acquisition of a deeper competence in the use of Moodle for language learning. The choice of the Italian context is influenced by the ongoing experimentation of Moodle in Italian secondary schools, but many suggestions can come only after having used the package and the Learning System for a long time. We should reach what Bax calls normalisation referring ‘to the stage when the technology becomes invisible, embedded in everyday practice and hence ‘normalised’. To take some commonplace examples, a wristwatch, a pen, shoes, and writing - these are all technologies which have become normalised to the extent that we hardly even recognise them as technologies’ (Bax, 2003). What is important, at the moment, is starting to explore new ways of teaching and keeping alive students' interest and motivation using their means of communication.
Read more
  • 0
  • 0
  • 3903
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 $19.99/month. Cancel anytime
article-image-restful-web-service-implementation-resteasy
Packt
18 Nov 2009
2 min read
Save for later

RESTful Web Service Implementation with RESTEasy

Packt
18 Nov 2009
2 min read
Getting the tools If you have already downloaded and installed Java's JDK and the Tomcat web server, you only need to download the JBoss's RESTEasy framework. Nevertheless, the complete list of the software needed for this article is as follows: Software Web Location Java JDK http://java.sun.com/ Apache Tomcat http://tomcat.apache.org/download-60.cgi Db4o http://developer.db4o.com/files/default.aspx RESTEasy Framework http://www.jboss.org/resteasy/ Install the latest Java JDK along with the latest version of Tomcat, if you haven't done so. Download and install Db4o and RESTEasy. Remember the location of the installs, as we'll need the libraries to deploy with the web application. RESTEasy — a JAX-RS implementation   RESTEasy is a full open source implementation of the JAX-RS specification. This framework works within any Java Servlet container, but because it's developed by JBoss, it offers extra features that are not part of the JAX-RS requirements. For example, RESTEasy offers out-of-the-box Atom support and also offers seamless integration with the EJB container portion of JBoss (none of these features are explored here). Web service architecture By now, you should be familiar with the coding pattern. Because we want to reuse a large portion of code already written, we have separate layers of abstraction. In this article, therefore, we only talk about the web layer and study in detail how to implement a full RESTful web service using RESTEasy. The full architecture of our web service looks as follows: In this diagram, we depict clients making HTTP requests to our web service. Each request comes to the web container, which then delegates the request to our RESTful layer that is composed of RESTEasy resource classes. The actual serialization of user and message records is delegated to our business layer, which in turns talks directly to our database layer (a Db4o database). Again, RESTEasy is a platform independent framework and works within any Servlet container. For this article we deploy our web service in Tomcat, as we've been working with it so far and are now familiar with deploying web applications to it, though we could as easily use the JBoss web container.
Read more
  • 0
  • 0
  • 3825

article-image-using-form-builder
Packt
11 Aug 2015
18 min read
Save for later

Using the Form Builder

Packt
11 Aug 2015
18 min read
In this article by Christopher John Pecoraro, author of the book, Mastering Laravel, you learn the fundamentals of using the form builder. (For more resources related to this topic, see here.) Building web pages with Laravel Laravel's approach to building web content is flexible. As much or as little of Laravel can be used to create HTML. Laravel uses the filename.blade.php convention to state that the file should be parsed by the blade parser, which actually converts the file into plain PHP. The name blade was inspired by the .NET's razor templating engine, so this may be familiar to someone who has used it. Laravel 5 provides a working demonstration of a form in the /resources/views/ directory. This view is shown when the /home route is requested and the user is not currently logged in. This form is obviously not created using the Laravel form methods. The route is defined in the routes file as follows: Route::get('home', 'HomeController@index'); The master template This is the following app (or master) template: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel</title> <link href="/css/app.css" rel="stylesheet"> <!-- Fonts --> <link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/ html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/ respond.min.js"></script> <![endif]--> </head> <body> <nav class="navbarnavbar-default"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" datatarget="# bs-example-navbar-collapse-1"> <span class="sr-only">Toggle Navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Laravel</a> </div> <div class="collapse navbar-collapse" id=" bs-example-navbar-collapse-1"> <ul class="navnavbar-nav"> <li><a href="/">Home</a></li> </ul> <ul class="navnavbar-navnavbar-right"> @if (Auth::guest()) <li><a href="{{ route('auth.login') }}">Login</a></li> <li><a href="/auth/register"> Register</a></li> @else <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ Auth::user()->name }} <span class="caret"></span></a> <ul class="dropdown-menu" role="menu"> <li><a href="/auth/ logout">Logout</a></li> </ul> </li> @endif </ul> </div> </div> </nav> @yield('content') <!-- Scripts --> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/ 2.1.3/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/twitterbootstrap/ 3.3.1/js/bootstrap.min.js"></script> </body> </html> The Laravel 5 master template is a standard HTML5 template with the following features: If the browser is older than Internet Explorer 9: Uses the HTML5 Shim from the CDN Uses the Respond.js JavaScript code from the CDN to retrofit media queries and CSS3 features Using @if (Auth::guest()), if the user is not authenticated, the login form is displayed; otherwise, the logout option is displayed Twitter bootstrap 3.x is included in the CDN The jQuery2.x is included in the CDN Any template that extends this template can override the content section An example page The source code for the login page is as follows: @extends('app') @section('content') <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Login</div> <div class="panel-body"> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form class="form-horizontal" role="form" method="POST" action="/auth/login"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> <div class="form-group"> <label class="col-md-4 controllabel"> E-Mail Address</label> <div class="col-md-6"> <input type="email" class="formcontrol" name="email" value="{{ old('email') }}"> </div> </div> <div class="form-group"> <label class="col-md-4 controllabel"> Password</label> <div class="col-md-6"> <input type="password" class="form-control" name="password"> </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <div class="checkbox"> <label> <input type="checkbox" name="remember"> Remember Me </label> </div> </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <button type="submit" lass="btn btn-primary" style="margin-right: 15px;"> Login </button> <a href="/password/email">Forgot Your Password?</a> </div> </div> </form> </div> </div> </div> </div> </div> @endsection From static HTML to static methods This login page begins with the following: @extends('app') It obviously uses the object-oriented paradigm to state that the app.blade.php template will be rendered. The following line overrides the content: @section('content') For this exercise, the form builder will be used instead of the static HTML. The form tag We will convert a static form tag to a FormBuilder method. The HTML is as follows: <form class="form-horizontal" role="form" method="POST"   action="/auth/login"> The method facade that we will use is as follows: Form::open(); In the FormBuilder.php class, the $reserved attribute is defined as follows: protected $reserved = ['method', 'url', 'route',   'action', 'files']; The attributes that we need to pass to an array to the open() method are class, role, method, and action. Since method and action are reserved words, it is necessary to pass the parameters in the following manner: Laravel form facade method array element HTML Form tag attribute method method url action role role class class Thus, the method call looks like this: {!! Form::open(['class'=>'form-horizontal', 'role =>'form', 'method'=>'POST', 'url'=>'/auth/login']) !!} The {!! !!} tags are used to start and end parsing of the form builder methods. The form method, POST, is placed first in the list of attributes in the HTML form tag. The action attribute actually needs to be a url. If the action parameter is used, then it refers to the controller action. In this case, the url parameter produces the action attribute of the form tag. Other attributes will be passed to the array and added to the list of attributes. The resultant HTML will be produced as follows: <form method="POST" action="http://laravel.example/auth/login" accept-charset="UTF-8" class="form-horizontal" role="form"> <input name="_token" type="hidden" value="wUY2hFSEWCzKHFfhywHvFbq9TXymUDiRUFreJD4h"> The CRSF token is automatically added, as the form method is POST. The text input field To convert the input fields, a facade is used. The input field's HTML is as follows: <input type="email" class="form-control" name="email" value="{{ old('email') }}"> Converting the preceding input field using a façade looks like this: {!! Form::input('email','email',old('email'), ['class'=>'form-control' ]) !!} Similarly, the text field becomes: {!! Form::input('password','password',null, ['class'=>'form-control']) !!} The input fields have the same signature. Of course, this can be refactored as follows: <?php $inputAttributes = ['class'=>'form-control'] ?> {!! Form::input('email','email',old('email'), $inputAttributes ) !!} ... {!! Form::input('password','password',null,$inputAttributes ) !!} The label tag The label tags are as follows: <label class="col-md-4 control-label">E-Mail Address</label> <label class="col-md-4 control-label">Password</label> To convert the label tags (E-Mail Address and Password), we will first create an array to hold the attributes, and then pass this array to the labels, as follows: $labelAttributes = ['class'=>'col-md-4 control-label']; Here is the form label code: {!! Form::label('email', 'E-Mail Address', $labelAttributes) !!} {!! Form::label('password', 'Password', $labelAttributes) !!} Checkbox To convert the checkbox to a facade, we will convert this: <input type="checkbox" name="remember"> Remember Me The preceding code is converted to the following code: {!! Form::checkbox('remember','') !!} Remember Me Remember that the PHP parameters should be sent in single quotation marks if there are no variables or other special characters, such as line breaks, inside the string to parse, while the HTML produced will have double quotes. The submit button Lastly, the submit button will be converted as follows: <button type="submit" class="btn btn-primary" style="margin-right: 15px;"> Login </button> The preceding code after conversion is as follows:   {!! Form::submit('Login', ['class'=>'btn btn-primary', 'style'=>'margin-right: 15px;']) !!} Note that the array parameter provides an easy way to provide any desired attributes, even those that are not among the list of standard HTML form elements. The anchor tag with links To convert the links, a helper method is used. Consider the following line of code: <a href="/password/email">Forgot Your Password?</a> The preceding line of code after conversion becomes: {!! link_to('/password/email', $title = 'Forgot Your Password?', $attributes = array(), $secure = null) !!} The link_to_route() method may be used to link to a route. For similar helper functions, visit http://laravelcollective.com/docs/5.0/html. Closing the form To end the form, we'll convert the traditional HTML form tag </form> to a Laravel {!! Form::close() !!} form method. The resultant form By putting everything together, the page now looks like this: @extends('app') @section('content') <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Login</div> <div class="panel-body"> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <?php $inputAttributes = ['class'=>'form-control']; $labelAttributes = ['class'=>'col-md-4 control-label']; ?> {!! Form::open(['class'=>'form-horizontal','role'=> 'form','method'=>'POST','url'=>'/auth/login']) !!} <div class="form-group"> {!! Form::label('email', 'E-Mail Address',$labelAttributes) !!} <div class="col-md-6"> {!! Form::input('email','email',old('email'), $inputAttributes) !!} </div> </div> <div class="form-group"> {!! Form::label('password', 'Password',$labelAttributes) !!} <div class="col-md-6"> {!! Form::input('password', 'password',null,$inputAttributes) !!} </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> <div class="checkbox"> <label> {!! Form::checkbox('remember','') !!} Remember Me </label> </div> </div> </div> <div class="form-group"> <div class="col-md-6 col-md-offset-4"> {!! Form::submit('Login',['class'=> 'btn btn-primary', 'style'=> 'margin-right: 15px;']) !!} {!! link_to('/password/email', $title = 'Forgot Your Password?', $attributes = array(), $secure = null); !!} </div> </div> {!! Form::close() !!} </div> </div> </div> </div> </div> @endsection Our example If we want to create a form to reserve a room in our accommodation, we can easily call a route from our controller: /** * Show the form for creating a new resource. * * @return Response */ public function create() { return view('auth/reserve'); } Now we need to create a new view that is located at resources/views/auth/reserve.blade.php. In this view, we can create a form to reserve a room in an accommodation where the user can select the start date, which comprises of the start day of the month and year, and the end date, which also comprises of the start day of the month and year. The form would begin as before, with a POST to reserve-room. Then, the form label would be placed next to the select input fields. Finally, the day, the month, and the year select form elements would be created as follows: {!! Form::open(['class'=>'form-horizontal', 'role'=>'form', 'method'=>'POST', 'url'=>'reserve-room']) !!} {!! Form::label(null, 'Start Date',$labelAttributes) !!} {!! Form::selectMonth('month',date('m')) !!} {!! Form::selectRange('date',1,31,date('d')) !!} {!! Form::selectRange('year',date('Y'),date('Y')+3) !!} {!! Form::label(null, 'End Date',$labelAttributes) !!} {!! Form::selectMonth('month',date('m')) !!} {!! Form::selectRange('date',1,31,date('d')) !!} {!! Form::selectRange('year',date('Y'), date('Y')+3,date('Y')) !!} {!! Form::submit('Reserve', ['class'=>'btn btn-primary', 'style'=>'margin-right: 15px;']) !!} {!! Form::close() !!} Month select Firstly, in the selectMonth method, the first parameter is the name of the input attribute, while the second attribute is the default value. Here, the PHP date method is used to extract the numeric portion of the current month—March in this case: {!! Form::selectMonth('month',date('m')) !!} The output, shown here formatted, is as follows: <select name="month"> <option value="1">January</option> <option value="2">February</option> <option value="3" selected="selected">March</option> <option value="4">April</option> <option value="5">May</option> <option value="6">June</option> <option value="7">July</option> <option value="8">August</option> <option value="9">September</option> <option value="10">October</option> <option value="11">November</option> <option value="12">December</option> </select> Date select A similar technique is applied for the selection of the date, but using the selectRange method, the range of the days in the month are passed to the method. Similarly, the PHP date function is used to send the current date to the method as the fourth parameter: {!! Form::selectRange('date',1,31,date('d')) !!} Here is the formatted output: <select name="date"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> ... <option value="28">28</option> <option value="29">29</option> <option value="30" selected="selected">30</option> <option value="31">31</option> </select> The date that should be selected is 30, since today is March 30, 2015. For the months that do not have 31 days, usually a JavaScript method would be used to modify the number of days based on the month and/or the year. Year select The same technique that is used for the date range is applied for the selection of the year; once again, using the selectRange method. The range of the years is passed to the method. The PHP date function is used to send the current year to the method as the fourth parameter: {!! Form::selectRange('year',date('Y'),date('Y')+3,date('Y')) !!} Here is the formatted output: <select name="year"> <option value="2015" selected="selected">2015</option> <option value="2016">2016</option> <option value="2017">2017</option> <option value="2018">2018</option> </select> Here, the current year that is selected is 2015. Form macros We have the same code that generates our month, date, and year selection form block two times: once for the start date and once for the end date. To refactor the code, we can apply the DRY (don't repeat yourself) principle and create a form macro. This will allow us to avoid calling the form element creation method twice, as follows: <?php Form::macro('monthDayYear',function($suffix='') { echo Form::selectMonth(($suffix!=='')?'month- '.$suffix:'month',date('m')); echo Form::selectRange(($suffix!=='')?'date- '.$suffix:'date',1,31,date('d')); echo Form::selectRange(($suffix!=='')?'year- '.$suffix:'year',date('Y'),date('Y')+3,date('Y')); }); ?> Here, the month, date, and year generation code is placed into a macro, which is inside the PHP tags, and it is necessary to add echo to print out the result. The monthDayYear name is given to this macro method. Calling our macro two times: once after each label; each time adding a different suffix via the $suffix variable. Now, our form code looks like this: <?php Form::macro('monthDayYear',function($suffix='') { echo Form::selectMonth(($suffix!=='')?'month- '.$suffix:'month',date('m')); echo Form::selectRange(($suffix!=='')?'date- '.$suffix:'date',1,31,date('d')); echo Form::selectRange(($suffix!=='')?'year- '.$suffix:'year',date('Y'),date('Y')+3,date('Y')); }); ?> {!! Form::open(['class'=>'form-horizontal', 'role'=>'form', 'method'=>'POST', 'url'=>'/reserve-room']) !!} {!! Form::label(null, 'Start Date',$labelAttributes) !!} {!! Form::monthDayYear('-start') !!} {!! Form::label(null, 'End Date',$labelAttributes) !!} {!! Form::monthDayYear('-end') !!} {!! Form::submit('Reserve',['class'=>'btn btn-primary', 'style'=>'margin-right: 15px;']) !!} {!! Form::close() !!} Conclusion The choice to include the HTML form generation package in Laravel 5 can ease the burden of having to create numerous HTML forms. This approach allows developers to use methods, create reusable macros, and use a familiar Laravel approach to build the frontend. Once the basic methods are learned, it is very easy to simply copy and paste the previously created form elements, and then change their element's name and/or the array that is sent to them. Depending on the size of the project, this approach may or may not be the right choice. For a very small application, the difference in the amount of code that needs to be written is not very evident, although, as is the case with the selectMonth and selectRange methods, the amount of code necessary is drastic. This technique, combined with the use of macros, makes it easy to reduce the occurrence of copy duplication. Also, one of the major problems with the frontend design is that the contents of the class of the various elements may need to change throughout the entire application. This would mean performing a large find and replace operation, where changes are required to be made to HTML, such as changing class attributes. By creating an array of attributes, including class, for similar elements, changes made to the entire form can be performed simply by modifying the array that those elements use. In a larger project, however, where parts of forms may be repeated throughout the application, the wise use of macros can easily reduce the amount of code necessary to be written. Not only this, but macros can isolate the code inside from changes that would require more than one block of code to be changed throughout multiple files. In the example, where the month, date, and year is to be selected, it is possible that this could be used up to 20 times in a large application. Any changes made to the desired block of HTML can be simply done to the macro and the result would be reflected in all of the elements that use it. Ultimately, the choice of whether or not to use this package will reside with the developer and the designer. Since a designer who wants to use an alternative frontend design tool may not prefer, nor be competent, to work with the methods in the package, he or she may want to not use it. Summary The construction of the master template was explained and then the form components, such as the various form input types, were shown through examples. Finally, the construction of a form for the room reservation, was explained, as well as a "do not repeat yourself" form macro creation technique. Resources for Article: Further resources on this subject: Eloquent… without Laravel! [Article] Laravel 4 - Creating a Simple CRUD Application in Hours [Article] Exploring and Interacting with Materials using Blueprints [Article]
Read more
  • 0
  • 0
  • 3814

article-image-integrating-moodle-20-alfresco-manage-content-business
Packt
29 Apr 2011
8 min read
Save for later

Integrating Moodle 2.0 with Alfresco to Manage Content for Business

Packt
29 Apr 2011
8 min read
  Moodle 2.0 for Business Beginner's Guide Implement Moodle in your business to streamline your interview, training, and internal communication processes. The Repository integration allows admins to set up external content management systems and use them to complement Moodle's own file management system. Using this integration you can now manage content outside of Moodle and publish it to the system once the document or other content is ready. The Portfolio integration enables users to store their Moodle content in an external e-portfolio system to share with evaluators, peers, and others. Managing content in repositories The repository system of Moodle 2 allows you to store and manipulate content outside of Moodle and easily add it to courses. By managing content outside of Moodle, you can provide users with a more robust editing experience. Many organizations utilize workflows and approval processes to ensure the accuracy of the content used in the LMS. A content repository can help you manage that process, and then make the content available on Moodle when it is ready for final publication. Using Alfresco to manage content Alfresco is an open source, enterprise content management system, similar in many ways to Microsoft Sharepoint or EMC's Documentum. Alfresco has seen widespread adoption over the last few years as more people begin to recognize the advantages of open source software. We will start by installing Alfresco, then look at how to link it to Moodle and add content to a Moodle site. At the end of this section, we'll take a look at Alfresco's content conversion services as a tool to ensure content is reliably converted to web friendly formats. Time for action - installing Alfresco on your test site To get us started, we'll install Alfresco on our test system to experiment with the integration. Alfresco runs on a different architecture than Moodle. Alfresco requires a Java application server instead of PHP. Fortunately, there are installers available on the Alfresco site that include everything we will need to develop a test system on your local computer. To install Alfresco, run through the following steps: Open your browser and go to http:www.alfresco.com. Go to the Downloads tab and select the Download Now button for Alfresco Document Management in the Community Edition column. Select the installer for your operating system and download it to your computer. Double-click on the installer (it may take a moment to get started). Select your language for the installer. Choose the database option you want to use. Use the included database, unless you have a good reason not to. When prompted, enter a database password. Be sure to write it down somewhere. The next screen will prompt you for an Alfresco admin password. Definitely write this down. The final screen will prompt you to choose the packages you want to install. Choose the defaults and click on Next. For the examples below, you will need to make sure that you have the OpenOffice component installed. The installer will begin to run. This will probably take a while, so it may be time to go and get a cup of tea. Once the installer is complete, select Launch. This will take a while as well, so a second cup of tea might be in order. Once Alfresco has launched, you can configure the interface with Moodle. What just happened You now have a full-functioning open source enterprise content management system installed on your personal computer. Alfresco has a lot of power for manipulating and sharing documents, but we will only focus on a few features for now. There are a lot of books available to help you learn how to use the more advanced features in Alfresco (a few of them from this publisher as well). Time for action - add a repository plugin to Moodle To allow users to access your new Alfresco repository, you will need to configure Moodle to allow access to the repository. The new repository architecture of Moodle 2 enables developers to create plugins to connect Moodle with other systems. Each system will have its own type of plugin to allow a direct connection between Moodle and the system. To enable Moodle to talk to an external repository, we need to enable the plugin and any associated options. To enable the Alfresco repository plug-in, go through the following steps: Login to Moodle as a Moodle admin. From the Site administration menu, select Plugins and then Repositories. The Manage repositories screen allows you to select from all of the available plugin repositories. For now, we will focus on the Alfresco repository. From the menu in the Active column, select Enabled and visible.The Alfresco plugin allows users in Moodle to add multiple instances of the repository. Most of the time, you will not want to allow users to add additional instances of the repository. As the admin, you can create a single site-wide instance of the repository plugin to allow users to link to Alfresco files. However, if you have more than one Alfresco instance, you can allow multiple users to create additional repositories at either the course level or the user level. Click the Save button to save the initial settings. This will return you to the Manage repositories page. Click on Settings under the Settings column to the right of the Alfresco repository row. This will take you back to the Alfresco settings page, but will provide an additional ability to add a repository instance at the site level. Click the Create a repository instance button at the bottom of the page. Give the name of your Alfresco instance. If this is an institutional repository, give it the same name as you commonly use. For example, if you commonly refer to your Alfresco instance as the "ECM" (for Enterprise Content Management), name the Alfresco instance ECM. Add the URL of your Alfresco site. Be sure to point to the Alfresco Explorer, not the Share application. You will also need to add the API pointer at the end of the string. For example, if you are pointing to the locally installed Alfresco which we described in the preceding case, the URL should be http://127.0.0.1:8080/alfresco/api. Click on Save. You will now have an instance of Alfresco available for users to add content to their courses. If you get the following error: Notice SOAP extension must be enabled for Alfresco plugin, then make sure that the SOAP library is enabled in your php.ini file. The location of the file will vary depending on the system you are using. Find the php.ini file and un-comment the extension=php_soap.dll line. Then restart Moodle and this should solve the error. What just happened You have just configured the Alfresco repository plugin to enable Moodle to talk to Alfresco. When you bring up the file picker in a course or at the site level, you should now see the Alfresco repository as an option. Have a go hero In the next article, we will configure the Google Docs plugin for Moodle, but there are a number of other plugins. Picasa and Flickr are two photo repositories on the web where many people share their photos. Wikimedia and YouTube are two very popular sources of media as well. Enable one or two of these additional plugins to practice configuring Moodle on your own. Time for action - adding content to Alfresco In Moodle 2, repository integrations are read-only. The Moodle design team decided the repository integration should only read from repositories, and the portfolio integration should save content to portfolio repositories. So you can't add content directly to Alfresco with the default plugin. To add content to the repository, we need to use the repository's own interface, then we can add it to Moodle. With Alfresco, that interface is either the Alfresco Explorer or Alfresco Share. To add content to the repository using Share, run through the following steps: Go to your Alfresco share interface, found at http://<your Alfresco server>/share. If your Alfresco is on your local machine with the default install, go to http://127.0.0.1:8080/share. Login with your username and password. Select the Repository link from the top of the page. This will display the folder structure for the default Alfresco repository. Select User Homes and then select your user space. From the menu above the file browser, select Upload. Click on the Select file(s) to upload button at the top of the Upload Files screen. Browse to find your file and then click on the Upload File(s) button. The file you selected should now appear in the file browser. What just happened You have now added a file to your Alfresco repository. We've explored a very simple example of adding a single file with no workflow or approval needed. You can use Share to create content, share it with colleagues, and use versioning and other features to manage the content creation process. Have a go hero Now that you've added a simple file to Alfresco Share, try some of the other features. Check out a file for editing, change it and check it back in for others to use, or create some content directly in Share.
Read more
  • 0
  • 0
  • 3810

article-image-eloquent-relationships
Packt
28 Jan 2013
12 min read
Save for later

Eloquent relationships

Packt
28 Jan 2013
12 min read
(For more resources related to this topic, see here.) 1 — Eloquent relationships ActiveRecord is a design pattern that describes an object-oriented way of interacting with your database. For example, your database's users table contains rows and each of these rows represents a single user of your site. Your User model is a class that extends the Eloquent Model class. When you query a record from your database, an instantiation of your User model class is created and populated with the information from the database. A distinct advantage of ActiveRecord is that your data and the business logic that is related to the data are housed within the same object. For example, it's typical to store the user's password in your model as a hash, to prevent it from being stored as plaintext. It's also typical to store the method, which creates this password hash within your User class. Another powerful aspect of the ActiveRecord pattern is the ability to define relationships between models. Imagine that you're building a blog site and your users are authors who must be able to post their writings. Using an ActiveRecord implementation, you are able to define the parameters of the relationship. The task of maintaining this relationship is then simplified dramatically. Simple code is the easy code to change. Difficult to understand code is the easy code to break. As a PHP developer, you're probably already familiar with the concept of database normalization. If you're not, normalization is the process of designing databases so that there is little redundancy in the stored data. For example, you wouldn't want to have both a users table which contains the user's name and a table of blog posts which also contains the author's name. Instead, your blog post record would refer to the user using their user ID. In this way we avoid synchronization problems and a lot of extra work! There are a number of ways in which relationships can be established in normalized database schemas. One-to-one relationship When a relationship connects two records in a way that doesn't allow for more records to be related, it is a one-to-one relationship. For example, a user record might have a one-to-one relationship with a passport record. In this example, a user record is not permitted to be linked to more than one passport record. Similarly, it is not permitted for a passport record to relate to more than one user record. How would the database look? Your users table contains information about each user in your database. Your passports table contains passport numbers and a link to the user which owns the passport. In this example, each user has no more than one passport and each passport must have an owner. The passports table contains its own id column which it uses as a primary key. It also contains the column user_id, which contains the ID of the user to whom the passport belongs. Last but not least, the passports table contains a column for the passport number. First, let's model this relationship in the User class: class User extends Eloquent { public function passport() { return $this->has_one('Passport'); } } We created a method named passport() that returns a relationship. It might seem strange to return relationships at first. But, you'll soon come to love it for the flexibility it offers. You'll notice that we're using the has_one() method and passing the name of the model as a parameter. In this case, a user has one passport. So, the parameter is the name of the passport model class. This is enough information for Eloquent to understand how to acquire the correct passport record for each user. Now, let's look at the Passport class: class Passport extends Eloquent { public function users() { return $this->belongs_to('User'); } } We're defining the passport's relationship differently. In the User class, we used the has_one() method. In the Passport class we used belongs_to(). It's vital to identify the difference early so that understanding the rest of the relationships is more simple. When a database table contains a foreign key, it is said that it belongs to a record in another table. In this example, our passports table refers to records in the users table through the foreign key user_id. Consequently, we would say that a passport belongs to a user. Since this is a one-to-one relationship the user has one (has_one()) passport. Let's say that we want to view the passport number of the user with the id of 1. $user = User::find(1); If(is_null($user)) { echo "No user found."; return; } If($user->passport) { echo "The user's passport number is " . $user->passport->number; } else { echo "This user has no passport."; } In this example, we're dutifully checking to make sure that our user object was returned as expected. This is a necessary step that should not be overlooked. Then, we check whether or not the user has a passport record associated with it. If a passport record for this user exists, the related object will be returned. If it doesn't exist, $user->passport will return null. In the preceding example, we test for the existence of a record and return the appropriate response. One-to-many relationships One-to-many relationships are similar to one-to-one relationships. In this relationship type, one model has many of other relationships, which in turn belongs to the former. One example of a one-to-many relationship is a professional sports team's relationship to its players. One team has many players. In this example, each player can only belong to one team. The database tables have the same structure. Now, let's look at the code which describes this relationship. class Team extends Eloquent { public function players() { return $this->has_many('Player'); } } class Player extends Eloquent { public function team() { return $this->belongs_to('Team'); } } This example is almost identical to the one-to-one example. The only difference is that the team's players() relationship uses has_many() rather than has_one(). The has_one() relationship returns a model object. The has_many() relationship returns an array of model objects. Let's display all of the players on a specific team: $team = Team::find(2); if(is_null($team)) { echo "The team could not be found."; } if(!$team->players) { echo "The team has no players."; } foreach($team->players as $player) { echo "$player->name is on team $team->name. "; } Again, we test to make sure that our team could be found. Then, we test to make sure that the team has players. Once we know that for sure, we can loop through those players and echo their names. If we tried to loop through the players without first testing and if the team had players, we'd get an error. Many-to-many relationships The last relationship type that we're going to cover is the many-to-many relationship. This relationship is different in that each record from each table could potentially be tied simultaneously to each record in another. We aren't storing foreign keys in either of these tables. Instead, we have a third table that exists solely to store our foreign keys. Let's take a look at the schema. Here we have a students table and a courses table. A student can be enrolled in many courses and a course can contain many students. The connection between students and courses is stored in a pivot table. A pivot table is a table that exists to connect two tables specifically for many-to-many relationships. Standard convention for naming a pivot table is to combine the names of both of the related tables, singularized, alphabetically ordered, and connected with an underscore. This gives us the table name course_student. This convention is not only used by Laravel and it's a good idea to follow the naming conventions covered in this document as strictly as possible as they're widely used in the web-development industry. It's important to notice that we're not creating a model for the pivot table. Laravel allows us to manage these tables without needing to interact with a model. This is especially nice because it doesn't make sense to model a pivot table with business logic. Only the students and courses are a part of our business. The connection between them is important, but only to the students and to the course. It's not important for its own sake. Let's define these models, shall we? class Student extends Eloquent { public function courses() { return $this->has_many_and_belongs_to('Course'); } } class Course extends Eloquent { public function students() { return $this->has_many_and_belongs_to('Student'); } } We have two models, each with the same type of relationship to each other. has_many_and_ belongs_to is a long name. But, it's a fairly simple concept. A course has many students. But, it also belongs to (belongs_to) student records and vice-versa. In this way, they are considered equal. Let's look at how we'll interact with these models in practice: $student = Student::find(1); if(is_null($student)) { echo "The student can't be found."; exit; } if(!$student->courses) { echo "The student $student->name is not enrolled in any courses."; exit; } foreach($student->courses as $course) { echo "The student $student->name is enrolled in the course $course->name."; } Here you can see that we can loop through the courses much the same way we could with the one-to-many relationship. Any time a relationship includes the word many, you know that you'll be receiving an array of models. Conversely, let's pull a course and see which students are a part of it. $course = Course::find(1); if(is_null($course)) { echo "The course can't be found."; exit; } if(!$course->students) { echo "The course $course->name seems to have no students enrolled."; exit; } foreach($course->students as $student) { echo "The student $student->name is enrolled in the course $course->name."; } The relationship functions exactly the same way from the course side. Now that we have established this relationship, we can do some fun things with it. Let's look at how we'd enroll a new student into an existing course: $course = Course::find(13); if(is_null($course)) { echo "The course can't be found."; exit; } $new_student_information = array( 'name' => 'Danielle' ); $course->students()->insert($new_student_information); Here we're adding a new student to our course by using the method insert(). This method is specific to this relationship type and creates a new student record. It also adds a record to the course_student table to link the course and the new student. Very handy! But, hold on. What's this new syntax? $course->students()->insert($new_student_information); Notice how we're not using $course->students->insert(). Our reference to students is a method reference rather than a property reference. That's because Eloquent handles methods that return relationship objects differently from other model methods. When you access a property of a model that doesn't exist, Eloquent will look to see if you have a function that matches that property's name. For example, if we try to access the property $course->students, Eloquent won't be able to find a member variable named $students. So it'll look for a function named students(). We do have one of those. Eloquent will then receive the relationship object from that method, process it, and return the resulting student records. If we access a relationship method as a method and not as a property, we directly receive the relationship object back. The relationship's class extends the Query class. This means that you can operate on a relationship object in the same way that you can operate on a query object, except that it now has new methods that are specific to the relationship type. The specific implementation details aren't important at this point. It's just important to know that we're calling the insert() method on the relationship object returned from $course->students(). Imagine that you have a user model and it has many relationships and belongs to a role model. Roles represent different permission groupings. Example roles might include customer, admin, super admin, and ultra admin. It's easy to imagine a user form for managing its roles. It would contain a number of checkboxes, one for each potential role. The name of the checkboxes is role_ids[] and each value represents the ID of a role in the roles table./p> When that form is posted we'll retrieve those values with the Input::get() method. $role_ids = Input::get('role_ids'); $role_ids is now an array that contains the values 1, 2, 3, and 4. $user->roles()->sync($role_ids); The sync() method is specific to this relationship type and is also perfectly suited for our needs. We're telling Eloquent to connect our current $user to the roles whose IDs exist within the $role_ids array. Let's look at what's going on here in further detail. $user->roles() is returning a has_ many_and_belongs_to relationship object. We're calling the sync() method on that object. Eloquent now looks at the $role_ids array and acknowledges it as the authoritative list of roles for this user. It then removes any records that shouldn't exist in the role_user pivot table and adds records for any role that should exist in the pivot table. Summary In this article we discussed three types of Eloquent relationships—one-to-one relationship, one-to-many relationship, and many-to-many ralationship. Resources for Article : Further resources on this subject: Modeling Relationships with GORM [Article] Working with Simple Associations using CakePHP [Article] NHibernate 2: Mapping relationships and Fluent Mapping [Article]
Read more
  • 0
  • 0
  • 3766
article-image-securing-moodle-instance
Packt
14 Feb 2011
7 min read
Save for later

Securing a Moodle Instance

Packt
14 Feb 2011
7 min read
Moodle Security Moodle is an open source CMS (Course Management System)/LMS (Learning Management System)/VLE (Virtual Learning Environment). Its primary purpose is to enable educational institutions and individuals to create and publish learning content in a coherent and pedagogically valuable manner, so that it can be used for successful knowledge transfer towards students. That sounds harmless enough. Why would anybody want to illegally access an educational platform? There are various motives of computer criminals. In general, they are people committed to the circumvention of computer security. This primarily concerns unauthorized remote computer break-ins via a communication network such as the Internet. Some of the motives could be: Financial: Stealing user and/or course information and selling it to other third-parties Personal: Personal grudge, infantile display of power, desire to alter assigned grades, and so on Weak points Moodle is a web application and as such must be hosted on a computer connected to some kind of network (private or public—Internet / Intranet). This computer must have the following components: Operating System (OS) Web server PHP Database server Moodle Each of these pieces can be used as a point of attack by a malicious user(s) in order to obtain access to the protected information. Therefore, it is our task to make all of them as secure as possible. The main focus will be directed towards our Moodle and PHP configuration. The secure installation of Moodle In this section we follow a secure installation of Moodle. In case you do not already have an installed instance of Moodle, we will show you the quickest way to do that, and at the same time focus on security. If you already have Moodle installed, go to the following section where you will see how to secure an existing installation of Moodle Starting from scratch In order to install Moodle on your server you need to install and configure the web server with support for PHP and the database server. We will not go into the specifics of setting up a particular web server, PHP, and/or database server right now, since it depends on the OS your server has installed. Also we will not explain in detail tasks like creating directories, setting up file permissions, etc as they are OS specific and out of the scope of this article. This section assumes you already know about your OS and have already configured your web server with an empty database. Every installation of Moodle must have: Web server with PHP support Dedicated database Two dedicated directories—one for Moodle and another for platform data We assume that your web server is Apache (Linux) or IIS (Windows), and that you use PHP 5.1.x or later and MySQL 5.0 or later. Installation checklist The following checklist will guide you through the basic installation procedure for Moodle. Download the latest stable version of Moodle from http://download. moodle.org/. (At the time of writing this article it is 1.9.8+). You have two options available on the download page—moodle-weekly-19.tgz or moodle-weekly-19.zip archive. In case you use Linux you can choose either. In case of Windows, ZIP file is the preferred choice. The reason for this is simple. Every Windows server comes, by default, with installed support for managing Zip archives. On the other hand, TGZ is readily available on every Linux distribution. Unpack the compressed file you just downloaded. This will produce a directory with the name moodle which contains all of the platform files. Move that directory to the web-root of your web server. After doing that it is recommended to make all files read-only for safety reasons. Create a directory called moodledata somewhere on the disk. Make sure that it is not in the web-root of your web server since that would incur a serious security breach. Doing that might expose all platform files submitted by course participants and teachers together with the course content to the outside world. Create an empty database (we suggest the name moodle or moodledb). The default database character set must be configured to utf8 and collation set to utf8_general_ci. It is recommended to have a special user for accessing this database with limited permissions. In case of credentials theft, a malicious user could only operate on data from one database, minimizing the potential damage. That database user account will need permissions for creating, altering, and deleting the tables, creating/dropping the indexes and reading/writing the data. Here is what you need to execute in your MySQL console for creating a database and user: CREATE DATABASE moodle CHARSET 'utf8' COLLATION 'utf8_general_ ci'; CREATE USER 'moodle'@'localhost' IDENTIFIED BY 'somepass'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON loomdb.* TO loom@localhost IDENTIFIED BY 'somepass'; FLUSH PRIVILEGES; Start the installation by opening the http://url to local installation of the moodle (for example http://localhost/moodle) in your browser. Make sure it is a more recent browser with pop ups and JavaScript enabled. We recommend Internet Explorer 8+ or Firefox 3.6+. You will see the following screenshot. On the next screen, we need to specify the web address of the platform and the location of the moodle directory on the disk. Now, we must configure database access. Choose MySQL as database type, localhost as host server, set the name of the database (moodle), database user, and its password (moodle/moodle). You should leave the table prefix as is. Moodle checks the server configuration on this screen and displays the outcome. We can proceed with the installation only if all of the minimal requirements are met. During installation, Moodle generates a configuration file within the moodle directory called config.php. It is important to make this file read-only after installation for security reasons. In case Moodle cannot save config.php it will offer to download or copy content of the file and manually place it in the appropriate location on the server. See the following screenshot: We are now presented with terms of usage and license agreement. To proceed click yes. We can now start the installation itself. During that process Moodle will create all of the tables in the database, session files in the moodledata directory, and load some initial information. Make sure you check Unattended operation at the bottom. That way, the process will be executed without user intervention. After the database setup is finished, we are offered a new screen where we must configure the administrative account. With this user you manage your platform, so be careful about disclosing this information to other users. Field name Description Recommended action Username Defines user name inside the Moodle. By default it is admin. We recommend leaving the default value unchanged. New password Defines user logon password. Must supply valid password. First name Defines name of the admin. Must supply valid name. Surname Defines surname of the admin. Must supply valid name. E-mail address Defines user e-mail address. Must supply valid e-mail. E-mail display Define the visibility of your e-mail address within the platform. We recommend leaving it as is (visible to all). E-mail active Defines whether e-mail is activated or not. Set it to enable. City/Town Defines name of the city where you live. Moodle requires this value. Select Country Name of your country. Set it to your country name. Timezone Sets your time zone so that server can display time calculated for your location in some reports. If not sure what your time zone is, leave it as is.   Preferred language Choose the platform language. By default, Moodle comes only with support for English language. If you want to add more languages visit http://download.moodle.org/ lang16/ and download and install the appropriate files.   After configuring administrative user there is just one more step to complete and that is setting up the site title and short name. In the Full site name field, place the long name you would like to set for your website; it can have multiple words. In the Short name for the site field put one word without spaces which will represent your website. In the Front Page Description field put a longer description (one paragraph) that explains in more detail the purpose of your site. This is optional and does not affect the Moodle functionality at all You have now finished installing Moodle and should see the following screenshot:
Read more
  • 0
  • 0
  • 3724

article-image-angularjs-project
Packt
19 Aug 2014
14 min read
Save for later

AngularJS Project

Packt
19 Aug 2014
14 min read
This article by Jonathan Spratley, the author of book, Learning Yeoman, covers the steps of how to create an AngularJS project and previewing our application. (For more resources related to this topic, see here.) Anatomy of an Angular project Generally in a single page application (SPA), you create modules that contain a set of functionality, such as a view to display data, a model to store data, and a controller to manage the relationship between the two. Angular incorporates the basic principles of the MVC pattern into how it builds client-side web applications. The major Angular concepts are as follows: Templates : A template is used to write plain HTML with the use of directives and JavaScript expressions Directives : A directive is a reusable component that extends HTML with the custom attributes and elements Models : A model is the data that is displayed to the user and manipulated by the user Scopes : A scope is the context in which the model is stored and made available to controllers, directives, and expressions Expressions : An expression allows access to variables and functions defined on the scope Filters : A filter formats data from an expression for visual display to the user Views : A view is the visual representation of a model displayed to the user, also known as the Document Object Model (DOM) Controllers : A controller is the business logic that manages the view Injector : The injector is the dependency injection container that handles all dependencies Modules : A module is what configures the injector by specifying what dependencies the module needs Services : A service is a piece of reusable business logic that is independent of views Compiler : The compiler handles parsing templates and instantiating directives and expressions Data binding : Data binding handles keeping model data in sync with the view Why Angular? AngularJS is an open source JavaScript framework known as the Superheroic JavaScript MVC Framework, which is actively maintained by the folks over at Google. Angular attempts to minimize the effort in creating web applications by teaching the browser's new tricks. This enables the developers to use declarative markup (known as directives or expressions) to handle attaching the custom logic behind DOM elements. Angular includes many built-in features that allow easy implementation of the following: Two-way data binding in views using double mustaches {{ }} DOM control for repeating, showing, or hiding DOM fragments Form submission and validation handling Reusable HTML components with self-contained logic Access to RESTful and JSONP API services The major benefit of Angular is the ability to create individual modules that handle specific responsibilities, which come in the form of directives, filters, or services. This enables developers to leverage the functionality of the custom modules by passing in the name of the module in the dependencies. Creating a new Angular project Now it is time to build a web application that uses some of Angular's features. The application that we will be creating will be based on the scaffold files created by the Angular generator; we will add functionality that enables CRUD operations on a database. Installing the generator-angular To install the Yeoman Angular generator, execute the following command: $ npm install -g generator-angular For Karma testing, the generator-karma needs to be installed. Scaffolding the application To scaffold a new AngularJS application, create a new folder named learning-yeoman-ch3 and then open a terminal in that location. Then, execute the following command: $ yo angular --coffee This command will invoke the AngularJS generator to scaffold an AngularJS application, and the output should look similar to the following screenshot: Understanding the directory structure Take a minute to become familiar with the directory structure of an Angular application created by the Yeoman generator: app: This folder contains all of the front-end code, HTML, JS, CSS, images, and dependencies: images: This folder contains images for the application scripts: This folder contains AngularJS codebase and business logic: app.coffee: This contains the application module definition and routing controllers: Custom controllers go here: main.coffee: This is the main controller created by default directives: Custom directives go here filters: Custom filters go here services: Reusable application services go here styles: This contains all CSS/LESS/SASS files: main.css: This is the main style sheet created by default views: This contains the HTML templates used in the application main.html: This is the main view created by default index.html: This is the applications' entry point bower_components: This folder contains client-side dependencies node_modules: This contains all project dependencies as node modules test: This contains all the tests for the application: spec: This contains unit tests mirroring structure of the app/scripts folder karma.conf.coffee: This file contains the Karma runner configuration Gruntfile.js: This file contains all project tasks package.json: This file contains project information and dependencies bower.json: This file contains frontend dependency settings The directories (directives, filters, and services) get created when the subgenerator is invoked. Configuring the application Let's go ahead and create a configuration file that will allow us to store the application wide properties; we will use the Angular value services to reference the configuration object. Open up a terminal and execute the following command: $ yo angular:value Config This command will create a configuration service located in the app/scripts/services directory. This service will store global properties for the application. For more information on Angular services, visit http://goo.gl/Q3f6AZ. Now, let's add some settings to the file that we will use throughout the application. Open the app/scripts/services/config.coffee file and replace with the following code: 'use strict' angular.module('learningYeomanCh3App').value('Config', Config = baseurl: document.location.origin sitetitle: 'learning yeoman' sitedesc: 'The tutorial for Chapter 3' sitecopy: '2014 Copyright' version: '1.0.0' email: 'jonniespratley@gmail.com' debug: true feature: title: 'Chapter 3' body: 'A starting point for a modern angular.js application.' image: 'http://goo.gl/YHBZjc' features: [ title: 'yo' body: 'yo scaffolds out a new application.' image: 'http://goo.gl/g6LO99' , title: 'Bower' body: 'Bower is used for dependency management.' image: 'http://goo.gl/GpxBAx' , title: 'Grunt' body: 'Grunt is used to build, preview and test your project.' image: 'http://goo.gl/9M00hx' ] session: authorized: false user: null layout: header: 'views/_header.html' content: 'views/_content.html' footer: 'views/_footer.html' menu: [ title: 'Home', href: '/' , title: 'About', href: '/about' , title: 'Posts', href: '/posts' ] ) The preceding code does the following: It creates a new Config value service on the learningYeomanCh3App module The baseURL property is set to the location where the document originated from The sitetitle, sitedesc, sitecopy, and version attributes are set to default values that will be displayed throughout the application The feature property is an object that contains some defaults for displaying a feature on the main page The features property is an array of feature objects that will display on the main page as well The session property is defined with authorized set to false and user set to null; this value gets set to the current authenticated user The layout property is an object that defines the paths of view templates, which will be used for the corresponding keys The menu property is an array that contains the different pages of the application Usually, a generic configuration file is created at the top level of the scripts folder for easier access. Creating the application definition During the initial scaffold of the application, an app.coffee file is created by Yeoman located in the app/scripts directory. The scripts/app.coffee file is the definition of the application, the first argument is the name of the module, and the second argument is an array of dependencies, which come in the form of angular modules and will be injected into the application upon page load. The app.coffee file is the main entry point of the application and does the following: Initializes the application module with dependencies Configures the applications router Any module dependencies that are declared inside the dependencies array are the Angular modules that were selected during the initial scaffold. Consider the following code: 'use strict' angular.module('learningYeomanCh3App', [ 'ngCookies', 'ngResource', 'ngSanitize', 'ngRoute' ]) .config ($routeProvider) -> $routeProvider .when '/', templateUrl: 'views/main.html' controller: 'MainCtrl' .otherwise redirectTo: '/' The preceding code does the following: It defines an angular module named learningYeomanCh3App with dependencies on the ngCookies, ngSanitize, ngResource, and ngRoute modules The .config function on the module configures the applications' routes by passing route options to the $routeProvider service Bower downloaded and installed these modules during the initial scaffold. Creating the application controller Generally, when creating an Angular application, you should define a top-level controller that uses the $rootScope service to configure some global application wide properties or methods. To create a new controller, use the following command: $ yo angular:controller app This command will create a new AppCtrl controller located in the app/scripts/controllers directory. file and replace with the following code: 'use strict' angular.module('learningYeomanCh3App') .controller('AppCtrl', ($rootScope, $cookieStore, Config) -> $rootScope.name = 'AppCtrl' App = angular.copy(Config) App.session = $cookieStore.get('App.session') window.App = $rootScope.App = App) The preceding code does the following: It creates a new AppCtrl controller with dependencies on the $rootScope, $cookieStore, and Config modules Inside the controller definition, an App variable is copied from the Config value service The session property is set to the App.session cookie, if available Creating the application views The Angular generator will create the applications' index.html view, which acts as the container for the entire application. The index view is used as the shell for the other views of the application; the router handles mapping URLs to views, which then get injected to the element that declares the ng-view directive. Modifying the application's index.html Let's modify the default view that was created by the generator. Open the app/index.html file, and add the content right below the following HTML comment: The structure of the application will consist of an article element that contains a header,<article id="app" <article id="app" ng-controller="AppCtrl" class="container">   <header id="header" ng-include="App.layout.header"></header>   <section id=”content” class="view-animate-container">     <div class="view-animate" ng-view=""></div>   </section>   <footer id="footer" ng-include="App.layout.footer"></footer> </article> In the preceding code: The article element declares the ng-controller directive to the AppCtrl controller The header element uses an ng-include directive that specifies what template to load, in this case, the header property on the App.layout object The div element has the view-animate-container class that will allow the use of CSS transitions The ng-view attribute directive will inject the current routes view template into the content The footer element uses an ng-include directive to load the footer specified on the App.layout.footer property Use ng-include to load partials, which allows you to easily swap out templates. Creating Angular partials Use the yo angular:view command to create view partials that will be included in the application's main layout. So far, we need to create three partials that the index view (app/index.html) will be consuming from the App.layout property on the $rootScope service that defines the location of the templates. Names of view partials typically begin with an underscore (_). Creating the application's header The header partial will contain the site title and navigation of the application. Open a terminal and execute the following command: $ yo angular:view _header This command creates a new view template file in the app/views directory. Open the app/views/_header.html file and add the following contents: <div class="header"> <ul class="nav nav-pills pull-right"> <li ng-repeat="item in App.menu" ng-class="{'active': App.location.path() === item.href}"> <a ng-href = "#{{item.href}}"> {{item.title}} </a> </li> </ul> <h3 class="text-muted"> {{ App.sitetitle }} </h3> </div> The preceding code does the following: It uses the {{ }} data binding syntax to display App.sitetitle in a heading element The ng-repeat directive is used to repeat each item in the App.menu array defined on $rootScope Creating the application's footer The footer partial will contain the copyright message and current version of the application. Open the terminal and execute the following command: $ yo angular:view _footer This command creates a view template file in the app/views directory. Open the app/views/_footer.html file and add the following markup: <div class="app-footer container clearfix">     <span class="app-sitecopy pull-left">       {{ App.sitecopy }}     </span>     <span class="app-version pull-right">       {{ App.version }}     </span> </div> The preceding code does the following: It uses a div element to wrap two span elements The first span element contains data binding syntax referencing App.sitecopy to display the application's copyright message The second span element also contains data binding syntax to reference App.version to display the application's version Customizing the main view The Angular generator creates the main view during the initial scaffold. Open the app/views/main.html file and replace with the following markup: <div class="jumbotron">     <h1>{{ App.feature.title }}</h1>     <img ng-src="{{ App.feature.image  }}"/>       <p class="lead">       {{ App.feature.body }}       </p>   </div>     <div class="marketing">   <ul class="media-list">         <li class="media feature" ng-repeat="item in App.features">        <a class="pull-left" href="#">           <img alt="{{ item.title }}"                       src="http://placehold.it/80x80"                       ng-src="{{ item.image }}"            class="media-object"/>        </a>        <div class="media-body">           <h4 class="media-heading">{{item.title}}</h4>           <p>{{ item.body }}</p>        </div>         </li>   </ul> </div> The preceding code does the following: At the top of the view, we use the {{ }} data binding syntax to display the title and body properties declared on the App.feature object Next, inside the div.marketing element, another div element is declared with the ng-repeat directive to loop for each item in the App.features property Then, using the {{ }} data binding syntax wrapped around the title and body properties from the item being repeated, we output the values Previewing the application To preview the application, execute the following command: $ grunt serve Your browser should open displaying something similar to the following screenshot: Download the AngularJS Batarang (http://goo.gl/0b2GhK) developer tool extension for Google Chrome for debugging. Summary In this article, we learned the concepts of AngularJS and how to leverage the framework in a new or existing project. Resources for Article: Further resources on this subject: Best Practices for Modern Web Applications [article] Spring Roo 1.1: Working with Roo-generated Web Applications [article] Understand and Use Microsoft Silverlight with JavaScript [article]
Read more
  • 0
  • 0
  • 3711

article-image-yii-11-using-zii-components
Packt
05 Sep 2011
10 min read
Save for later

Yii 1.1: Using Zii Components

Packt
05 Sep 2011
10 min read
  (For more resources on this subject, see here.) Introduction Yii have a useful library called Zii. It's bundled with framework and includes some classes aimed to make the developer's life easier. Its most handy components are grids and lists which allow you to build data in both the admin and user parts of a website in a very fast and efficient way. In this article you'll learn how to use and adjust these components to fit your needs. Also you'll learn about data providers. They are part of the core framework, not Zii, but since they are used extensively with grids and lists, we'll review them here. We'll use Sakila sample database version 0.8 available from official MySQL website: http://dev.mysql.com/doc/sakila/en/sakila.html. Using data providers Data providers are used to encapsulate common data model operations such as sorting, pagination and querying. They are used with grids and lists extensively. Because both widgets and providers are standardized, you can display the same data using different widgets and you can get data for a widget from various providers. Switching providers and widgets is relatively transparent. Currently there are CActiveDataProvider, CArrayDataProvider, and CSqlDataProvider implemented to get data from ActiveRecord models, arrays, and SQL queries respectively. Let's try all these providers to fill a grid with data. Getting ready Create a new application using yiic webapp as described in the official guide. Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html and execute the downloaded SQLs: first schema then data. Configure the DB connection in protected/config/main.php. Use Gii to create a model for the film table. How to do it... Let's start with a view for a grid controller. Create protected/views/grid/index.php: <?php $this->widget('zii.widgets.grid.CGridView', array('dataProvider' => $dataProvider,))?> Then create a protected/controllers/GridController.php: <?phpclass GridController extends Controller{ public function actionAR() { $dataProvider = new CActiveDataProvider('Film', array( 'pagination'=>array( 'pageSize'=>10, ), 'sort'=>array( 'defaultOrder'=> array('title'=>false), ) )); $this->render('index', array( 'dataProvider' => $dataProvider, )); } public function actionArray() { $yiiDevelopers = array( array( 'name'=>'Qiang Xue', 'id'=>'2', 'forumName'=>'qiang', 'memberSince'=>'Jan 2008', 'location'=>'Washington DC, USA', 'duty'=>'founder and project lead', 'active'=>true, ), array( 'name'=>'Wei Zhuo', 'id'=>'3', 'forumName'=>'wei', 'memberSince'=>'Jan 2008', 'location'=>'Sydney, Australia', 'duty'=>'project site maintenance and development', 'active'=>true, ), array( 'name'=>'Sebastián Thierer', 'id'=>'54', 'forumName'=>'sebas', 'memberSince'=>'Sep 2009', 'location'=>'Argentina', 'duty'=>'component development', 'active'=>true, ), array( 'name'=>'Alexander Makarov', 'id'=>'415', 'forumName'=>'samdark', 'memberSince'=>'Mar 2010', 'location'=>'Russia', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Maurizio Domba', 'id'=>'2650', 'forumName'=>'mdomba', 'memberSince'=>'Aug 2010', 'location'=>'Croatia', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Y!!', 'id'=>'1644', 'forumName'=>'Y!!', 'memberSince'=>'Aug 2010', 'location'=>'Germany', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Jeffrey Winesett', 'id'=>'15', 'forumName'=>'jefftulsa', 'memberSince'=>'Sep 2010', 'location'=>'Austin, TX, USA', 'duty'=>'documentation and marketing', 'active'=>true, ), array( 'name'=>'Jonah Turnquist', 'id'=>'127', 'forumName'=>'jonah', 'memberSince'=>'Sep 2009 - Aug 2010', 'location'=>'California, US', 'duty'=>'component development', 'active'=>false, ), array( 'name'=>'István Beregszászi', 'id'=>'1286', 'forumName'=>'pestaa', 'memberSince'=>'Sep 2009 - Mar 2010', 'location'=>'Hungary', 'duty'=>'core framework development', 'active'=>false, ), ); $dataProvider = new CArrayDataProvider( $yiiDevelopers, array( 'sort'=>array( 'attributes'=>array('name', 'id', 'active'), 'defaultOrder'=>array('active' => true, 'name' => false), ), 'pagination'=>array( 'pageSize'=>10, ), )); $this->render('index', array( 'dataProvider' => $dataProvider, )); } public function actionSQL() { $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM film')->queryScalar(); $sql='SELECT * FROM film'; $dataProvider=new CSqlDataProvider($sql, array( 'keyField'=>'film_id', 'totalItemCount'=>$count, 'sort'=>array( 'attributes'=>array('title'), 'defaultOrder'=>array('title' => false), ), 'pagination'=>array( 'pageSize'=>10, ), )); $this->render('index', array( 'dataProvider' => $dataProvider, )); }} Now run grid/aR, grid/array and grid/sql actions and try using the grids. How it works... The view is pretty simple and stays the same for all data providers. We are calling the grid widget and passing the data provider instance to it. Let's review actions one by one starting with actionAR: $dataProvider = new CActiveDataProvider('Film', array( 'pagination'=>array( 'pageSize'=>10, ), 'sort'=>array( 'defaultOrder'=>array('title'=>false), ))); CActiveDataProvider works with active record models. Model class is passed as a first argument of class constructor. Second argument is an array that defines class public properties. In the code above, we are setting pagination to 10 items per page and default sorting by title. Note that instead of using a string we are using an array where keys are column names and values are true or false. true means order is DESC while false means that order is ASC. Defining the default order this way allows Yii to render a triangle showing sorting direction in the column header. In actionArray we are using CArrayDataProvider that can consume any array. $dataProvider = new CArrayDataProvider($yiiDevelopers, array( 'sort'=>array( 'attributes'=>array('name', 'id', 'active'), 'defaultOrder'=>array('active' => true, 'name' => false), ), 'pagination'=>array( 'pageSize'=>10, ),)); First argument accepts an associative array where keys are column names and values are corresponding values. Second argument accepts an array with the same options as in CActiveDataProvider case. In actionSQL, we are using CSqlDataProvider that consumes the SQL query and modifies it automatically allowing pagination. First argument accepts a string with SQL and a second argument with data provider parameters. This time we need to supply calculateTotalItemCount with total count of records manually. For this purpose we need to execute the extra SQL query manually. Also we need to define keyField since the primary key of this table is not id but film_id. To sum up, all data providers are accepting the following properties: pagination CPagination object or an array of initial values for new instance of CPagination. sort CSort object or an array of initial values for new instance of CSort. totalItemCount We need to set this only if the provider, such as CsqlDataProvider, does not implement the calculateTotalItemCount method. There's more... You can use data providers without any special widgets. Replace protected/views/grid/ index.php content with the following: <?php foreach($dataProvider->data as $film):?> <?php echo $film->title?><?php endforeach?> <?php $this->widget('CLinkPager',array( 'pages'=>$dataProvider->pagination))?> Further reading To learn more about data providers refer to the following API pages:   http://www.yiiframework.com/doc/api/CDataProvider http://www.yiiframework.com/doc/api/CActiveDataProvider http://www.yiiframework.com/doc/api/CArrayDataProvider http://www.yiiframework.com/doc/api/CSqlDataProvider http://www.yiiframework.com/doc/api/CSort http://www.yiiframework.com/doc/api/CPagination Using grids Zii grids are very useful to quickly create efficient application admin pages or any pages you need to manage data on. Let's use Gii to generate a grid, see how it works, and how we can customize it. Getting ready Carry out the following steps: Create a new application using yiic webapp as described in the official guide. Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html. Execute the downloaded SQLs: first schema then data. Configure the DB connection in protected/config/main.php. Use Gii to create models for customer, address, and city tables. How to do it... Open Gii, select Crud Generator, and enter Customer into the Model Class field. Press Preview and then Generate. Gii will generate a controller in protected/controllers/CustomerController.php and a group of views under protected/views/customer/. Run customer controller and go to Manage Customer link. After logging in you should see the grid generated: How it works... Let's start with the admin action of customer controller: public function actionAdmin(){ $model=new Customer('search'); $model->unsetAttributes(); // clear any default values if(isset($_GET['Customer'])) $model->attributes=$_GET['Customer']; $this->render('admin',array( 'model'=>$model, ));} Customer model is created with search scenario, all attribute values are cleaned up, and then filled up with data from $_GET. On the first request $_GET is empty but when you are changing the page, or filtering by first name attribute using the input field below the column name, the following GET parameters are passed to the same action via an AJAX request: Customer[address_id] =Customer[customer_id] =Customer[email] =Customer[first_name] = alexCustomer[last_name] =Customer[store_id] =Customer_page = 2ajax = customer-grid Since scenario is search, the corresponding validation rules from Customer::rules are applied. For the search scenario, Gii generates a safe rule that allows to mass assigning for all fields: array('customer_id, store_id, first_name, last_name, email, address_id, active, create_date, last_update', 'safe','on'=>'search'), Then model is passed to a view protected/views/customer/admin.php. It renders advanced search form and then passes the model to the grid widget: <?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'customer-grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( 'customer_id', 'store_id', 'first_name', 'last_name', 'email', 'address_id', /* 'active', 'create_date', 'last_update', */ array( 'class'=>'CButtonColumn', ), ),)); ?> Columns used in the grid are passed to columns. When just a name is passed, the corresponding field from data provider is used. Also we can use custom column represented by a class specified. In this case we are using CButtonColumn that renders view, update and delete buttons that are linked to the same named actions and are passing row ID to them so action can be done to a model representing specific row from database. filter property accepts a model filled with data. If it's set, a grid will display multiple text fields at the top that the user can fill to filter the grid. The dataProvider property takes an instance of data provider. In our case it's returned by the model's search method : public function search(){ // Warning: Please modify the following code to remove attributes that // should not be searched. $criteria=new CDbCriteria; $criteria->compare('customer_id',$this->customer_id); $criteria->compare('store_id',$this->store_id); $criteria->compare('first_name',$this->first_name,true); $criteria->compare('last_name',$this->last_name,true); $criteria->compare('email',$this->email,true); $criteria->compare('address_id',$this->address_id); $criteria->compare('active',$this->active); $criteria->compare('create_date',$this->create_date,true); $criteria->compare('last_update',$this->last_update,true); return new CActiveDataProvider(get_class($this), array( 'criteria'=>$criteria, ));} This method is called after the model was filled with $_GET data from the filtering fields so we can use field values to form the criteria for the data provider. In this case all numeric values are compared exactly while string values are compared using partial match.
Read more
  • 0
  • 0
  • 3685
article-image-formatting-and-enhancing-your-moodle-materials-part-1
Packt
18 Nov 2009
7 min read
Save for later

Formatting and Enhancing Your Moodle Materials: Part 1

Packt
18 Nov 2009
7 min read
There are three main types of Moodle pages to consider when it comes to design: Moodle front pages Moodle course pages Moodle activities Before we go into detail about design considerations, let's look at examples of each of these to see how we can improve them with a few basic steps. Moodle front page If we take Moodle straight out of the box, set up some blocks for the main menu, provide some useful links, and set the front page settings to show a list of courses, we could have something like this: BEFORE It's functional enough, but not very engaging. Just by making a few changes, we can make the front page much more interesting and readable: AFTER What's changed? There's a new theme (Moodle speak for the color scheme and automatic font choices). As we'll see in a bit, some themes also include tabs and drop-down menus. There's an appropriate image in the top-center of the screen to draw users in. The About this site block has a photo of the administrator, which provides a personal touch. There's an easily-identifiable "start here icon"—another helpful feature that guides your users in the right direction. Moodle course page Like the Moodle front page, a standard course page automatically creates three columns for us to fill with text. If we choose a topics format from the Settings menu and write out a list of activities and links for our course, it could look something like this: BEFORE The problem here is that it's difficult to distinguish important information from unimportant information. There's a lot of scrolling to be done, and there are no visual clues as to what the course page is about. Here's one way of transforming the page: AFTER What's changed? There's a new theme. The theme includes tabs with links to key parts of the site. There's an image related to the course topic (teaching) at the top of the course page. The long list in the previous version has been reduced to a more manageable size. Important information is at the top of the page, and is in a larger font size. It contrasts with less important information, which has a smaller font size. Lines are used to separate different sorts of information. There is more color harmony—at attempt to get the colors to blend. There's an avatar introduction in the left block for new users. Moodle activity When we're pushed for time, it's all too tempting just to set out a list of references without paying due attention to instructions and a helpful hierarchy of information, as in the following example: BEFORE There's a lot of information here. We can use the Book module to organize the information, and make the page more readable, as in the following transformation: AFTER What's changed? The previous list has been divided into sections in the Book module There's a "how-to" section at the beginning of the Table of Contents Graphics from the target websites have been included as visual clues The Tool labels such as Audacity and Findsounds are in a larger font size to make them stand out An action girl icon indicates task instructions Task instructions are in bold blue to make them stand out A grid is used to separate sections As we can see, by enhancing the visual design of our sites we can make our materials more engaging and effective. We can also make them more attractive by improving the quality of the audio, images, and video that we use. Here are some principles we could take on board: Contrast Consider hierarchies of importance in your materials. The default font size on HTML pages is 12 points, similar to what you're reading now. Vary the size to make more important information stand out. You can also use images, buttons, and navigation signs to help users see the function of pages and content more quickly and remember it. Consistency Being consistent in your use of fonts for certain sorts of information, font sizes for ranking information, and navigation links will make it easier for users to understand the site and will make it more aesthetically pleasing. It's also better not to use too many different fonts or make your site too fancy or you will end up with a dog's breakfast. As a rule, it'll look better if you use different sizes of a limited number of fonts, rather than including lots of different fonts. To promote design consistency on your Moodle site, consider setting up a style guide so that all teachers use the same design framework. Alignment A basic principle of graphic design is to make sure that the objects on your page are aligned with each other. Imagine a grid that they stick to. Aligned objects look more professional and enhance contrast within pages. Moodle organizes that automatically for us with front pages and course pages, but when we set up instruction pages for activities, we need to keep alignment principles in mind, as we have more design freedom. Quality Aim for the best quality audio recordings and images. It is likely to make a big difference to language learners if they can listen to clear recordings and easily identify the content of images. This article Each of the following sections in this article contributes to the above principles by demonstrating some of the tools available in Moodle that help you with your design. You'll find a consideration of these and other website design issues at http://www.asktog.com/basics/firstPrinciples.html. Here are the main topics covered in this article: Text Images Videos Sound Navigation Blocks Layout Style guide Accessibility Feedback Text There are two main ways of entering text in Moodle: Adding text pages Adding web pages using the HTML editor The most common way is by using the HTML editor. Most of this section on text will look at formatting options using that. Adding text pages When you select Add a resource... and then Compose a text page, you get a choice of formatting options for your page. You might find it useful to use the Moodle auto-format, as it automatically creates emoticons, paragraphs, and hyperlinks for you if you write in web addresses. Creating hyperlinks is a little more time-consuming if you choose the HTML format, as you have to create all hyperlinks manually. Markdown format is also useful if you want to create a structured document with lists and emphasis. You can, of course, produce all these in the HTML format, using the editing menu. The following options are available when you select Add a resource... and then Compose a text page. Formatting options Details Moodle auto-format This has limited formatting options, but will automatically turn URLs like http://moodle.org into hyperlinks and will include emoticons like J when you type :). It keeps line breaks and converts blank lines into new paragraphs. HTML format This does not automatically format text, but gives you a wide range of possibilities for editing your text. It allows you to change font faces, font sizes, and color, as well as embed graphic images, sound, and video. Note that if you select Compose a text page and then the HTML format option, you will need to enter pure HTML-that's the code that produces web pages. If you are not familiar with HTML, you'll be better off choosing Compose a web page and then using the HTML graphic editor. Plain text format This format keeps spaces and new lines, but no other formatting is available. Markdown format Markdown allows you to easily add emphasis (bold, italics), structure (bullet points and headings), and links (to images or other web resources). You can use Markdown in many places in Moodle. Simply select it from the formatting drop-down list, which is found below the text entry area, wherever you have the choice.  
Read more
  • 0
  • 0
  • 3679

article-image-working-cxf-tool
Packt
18 Jan 2010
9 min read
Save for later

Working with CXF Tool

Packt
18 Jan 2010
9 min read
Invoking a web service using the Java client A web service exposes a set of operations over the network, typically via HTTP protocol. In order to invoke the web services, the web service client needs to know the following information: What operations are exposed by the web service The input and output message formats required to access the service operations What protocol, for instance HTTP or JMS, to use to invoke the web service The URL location of the web service All of the above information is contained in the standard XML descriptor called WSDL (Web Service Description Language). The WSDL file provides a format contract between the web service provider and the web service client. The web service client typically inspects the WSDL file to determine what operations are exposed by the web service, what parameters need to be supplied to invoke the web service operation and to formulate the request, and invokes the web service over the supported protocol. Similarly, the web service clients need to write the code to inspect the response and convert it into the required format. CXF hides the complexity of creating web service clients by providing the WSDL to Java command line tool, which takes a WSDL file and generates client code. The client code can be used by developers with no changes to invoke the web services. In this section, we will look at how to generate client code from an existing WSDL. For this example, we will take a real world scenario, where we will invoke a .NET service located over the Web using the Java client generated by the WSDL to Java tool. This shows the true power of web service interoperability, where applications implemented in different languages can communicate with each other. The process of generating web service clients does not differ for web services implemented in different languages, as you generate web service clients from WSDL and XML Schema definitions. Before invoking the .NET service, let's examine the WSDL to determine which operations are exposed by the web service. Analyzing the service WSDL definition We will invoke a publicly available .NET web service located at http://www.ignyte.com/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx?wsdl. This web service retrieves US Theaters and Movie Showtime information based on a valid US zip code and a radius supplied by the web service clients. The .NET web service is a WS-I compliant web service. The Web Services Interoperability Organization (WS-I), an open industry organization, was formed to promote web services interoperability across platforms, operating systems, and programming languages. One concrete product of WS-I is the Basic Profile. Basic Profile narrows the scope of specifications to a reasonable set of rules and guidelines that are best suited to help interoperability. If you type in the given URL in the browser, you see the WSDL definition, as shown in the following screenshot: Let's analyze the important sections of the WSDL file to get an understanding of which operations are exposed by the movie information web service and which message formats are required to invoke the web service. The web service provides two operations, GetTheatersAndMovies and GetUpcomingMovies, as shown in listing below. For this article, we will focus on how to invoke the GetTheatersAndMovies operation. The GetTheatersAndMovies takes the GetTheatersAndMoviesSoapIn message as the input and provides GetTheatersAndMoviesSoapOut as the output message. <wsdl:portType name="MovieInformationSoap"> <wsdl:operation name="GetTheatersAndMovies"> <wsdl:documentation >This method will retrieve a list of all theaters and the moviesplaying today.</wsdl:documentation> <wsdl:input message="tns:GetTheatersAndMoviesSoapIn" /> <wsdl:output message="tns:GetTheatersAndMoviesSoapOut" /> </wsdl:operation></wsdl:portType> The web service client invokes the GetTheatersAndMovies operation to get theater and movie information. The input to the GetTheatersAndMovies operation is the GetTheatersAndMoviesSoapIn XML message. The GetTheatersAndMoviesSoapIn message references the GetTheatersAndMovies element, which defines the actual XML schema definition for the input message. The following is the code listing of GetTheatersAndMovies schema definition: <s:element name="GetTheatersAndMovies"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="zipCode" type="s:string" /> <s:element minOccurs="1" maxOccurs="1" name="radius" type="s:int" /> </s:sequence> </s:complexType></s:element> The GetTheatersAndMovies contains an element zipCode of type String and radius which is of type integer that needs to be passed as input by the web services client as an input to the GetTheatersAndMoviesSoapIn operation. The minOccurs and maxOccurs attribute associated with zipCode and radius is used to specify the minimum and maximum occurrence of the element inside a GetTheatersAndMovies element. The zipCode and radius element can appear only once inside a GetTheatersAndMovies element as it specifies the value of maxOccurs="1". If maxOccurs has the value Unbounded, then it implies that multiple occurrences of the element can exist. Similarly, the GetTheatersAndMoviesResponse specifies the output message format for the response. The following is the code listing of the GetTheatersAndMoviesResponse schema definition. We will break down the schema for better understanding: The GetTheatersAndMoviesResponse schemaThe following shows the definition of GetTheatersAndMoviesResponse. The GetTheatersAndMoviesResponse contains an element ArrayOfTheater. <s:element name="GetTheatersAndMoviesResponse"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="GetTheatersAndMoviesResult" type= "tns:ArrayOfTheater" /> </s:sequence> </s:complexType></s:element> The ArrayOfTheater SchemaThe following shows the definition of ArrayOfTheater schema.The ArrayOfTheater is an array which consists of Theatre elements.The maxOccurs="unbounded" specifies that multiple occurrences of Theatre elements can exist in an ArrayOfTheater element. <s:complexType name="ArrayOfTheater"> <s:sequence> <s:element minOccurs="0" maxOccurs= "unbounded" name="Theater" nillable= "true" type="tns:Theater" /> </s:sequence></s:complexType> The Theater SchemaThe Theater elements consist of the Name and Address elements of type String, which specifies the name and address of the Theater and an array of ArrayOfMovie element. <s:complexType name="Theater"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="Address" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="Movies" type="tns:ArrayOfMovie" /> </s:sequence></s:complexType> The ArrayOfMovie SchemaThe following is the ArrayOfMovie definition. The ArrayOfMovie is an array which consists of Movie elements. The maxOccurs="unbounded" specifies that multiple occurrences of Movie elements can exist in an ArrayOfMovie element. <s:complexType name="ArrayOfMovie"> <s:sequence> <s:element minOccurs="0" maxOccurs= "unbounded" name="Movie" nillable= "true" type="tns:Movie" /> </s:sequence></s:complexType> The Movie SchemaThe Movie element contains details of movies such as ratings, names of the movies, running times and show times represented as String type. <s:complexType name="Movie"> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="Rating" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="RunningTime" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="ShowTimes" type="s:string" /> </s:sequence></s:complexType> Based on the Schema definitions above, the CXF WSDL2Java tool generates Java code that maps to these XML elements. The web service clients communicate with the web services using these generated Java objects to invoke a Java method representing the GetTheatersAndMoviesoperation and leave the SOAP XML to Java conversion and low level implementation details with the CXF framework. The SOAP address in the WSDL file specifies the location of the service, which is http://www.ignyte.com/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx, as shown in the listing below: <wsdl:service name="MovieInformation"> <wsdl:port name="MovieInformationSoap" binding= "tns:MovieInformationSoap"> <soap:address location="http://www.ignyte.com/webservices/ ignyte.whatsshowing.webservice/moviefunctions.asmx" /> </wsdl:port> <wsdl:port name="MovieInformationSoap12" binding= "tns:MovieInformationSoap12"> <soap12:address location="http://www.ignyte.com/webservices/ ignyte.whatsshowing.webservice/moviefunctions.asmx" /> </wsdl:port> </wsdl:service></wsdl:definitions> We will now look at how to generate the web service client code for the Movie information web service. Building and running the Java web service clients The source code and build files for the example are available in the wsdl2Java folder of the downloaded source code. We will follow the steps below to build and execute the web service client: Generate the web service clients Analyze the generated artifacts Modify the generated code Build the web service client Run the web service client Generate the web service clients We will use the Ant build script (build.xml) for generating the web service client code and building the project code as shown below. Navigate to the wsdl2java folder of the downloaded source code. Execute the cxfWSDLToJava target by navigating to the wsdl2java folder and running the following command: ant cxfWSDLToJava The following figure shows the output generated upon running the ant command: The cxfWSDLToJava ant target calls the CXF tool apache.cxf.tools.wsdlto.WSDLToJava to generate web service client code based on the URL http://www.ignyte.com/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx?wsdl The following is a code snippet of ant target cxfWSDLToJava in build.xml: <target name="cxfWSDLToJava"> <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true"> <arg value="-client"/> <arg value="-d"/> <arg value="src"/> <arg value="http://www.ignyte.com/webservices/ignyte. whatsshowing.webservice/moviefunctions.asmx?wsdl"/> <classpath> <path refid="cxf.classpath"/> </classpath> </java></target> WSDLToJava generates JAX-WS compliant Java code for the services defined in the WSDL document. Based on the parameters passed, it can generate the starting point of the code for developing the web service client and service. The client option, as shown in above snippet, generates the client code. The following is a list of augments and descriptions supported by the WSDLToJava tool extracted as it is from the CXF website—http://cwiki.apache.org/CXF20DOC/wsdl-to-java.html
Read more
  • 0
  • 0
  • 3678
Modal Close icon
Modal Close icon