DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Languages Topics

article thumbnail
Practical PHP Patterns: Table Data Gateway
The Table Data Gateway pattern is the object-oriented equivalent of a relational table. In fact, this pattern's intent is to encapsulate the full interaction with a database table, holding all the logic specific to this particular implementation of the back end. In the majority of cases, a Table Data Gateway deals with a relational model, having a 1:1 relationship with the main tables of the database. Minor tables may not need a specific class, or can be managed via Table Data Gateways of tables that link them with foreign keys (for example entities introduced to store M:N relationships are usually not first-class citizens.) In the relational implementation, the Table Data Gateway handles all SQL queries, presenting a domain-specific interface when a class is coded for a specific table, or a generic one when a generic implementation is reused throughout different applications. The difference between the two APIs may be something like findBy($field, $value) (generic) versus findByPrice($price) (domain-specific). Note that in PHP magic methods are often used to implement domain-specific interfaces without code generation: a __call() implementation can catch the various findBy*() method and throw exceptions if the methods is not applicable. Related patterns Although, the concept of table is already correlated with a relational model (and it does not hold when the back end is an object-oriented database or one of the key-value stores so trendy today), this pattern is named Gateway because it is a specialization of the Gateway category of pattern, which decouple an object graph (or any in-memory structures) from external infrastructure like databases, web services, filesystems and so on. In fact, there is an alternate name for this pattern: Data Access Object (or DAO for friends). Although if I was pedantic I would highlight the differences between the implementations of DAOs and Table Data Gateway, their intent is really the same and there are differences in an individual pattern implementations that are greater than the ones between the different patterns. There's no clear demarcation line between the two. Another related pattern is the Table Module one. Table Data Gateway does not work against, but with a Table Module, providing a separation of concerns: the first object takes the rows out of the database, while the second performs in-memory operation on them (generally by composing the Table Data Gateway or its results). The in-memory operations of a Table Module are easier to test, but the SQL-based operations of the Table Data Gateway are pushed on the database side: there is a trade-off between the logic should be kept in each class. When used in isolation, the Table Data Gateway is also a Factory for also for Row Data Gateways or Active Records, both again implemented with generic or domain-specific interfaces. Many frameworks and first-generation PHP ORMs based on Active Record are also based on Table Data Gateway to provide a collection-level access to the objects stored as rows. In the context of Active Record, the only alternative to a Table Data Gateway to handle operations like find() is to place static methods on the Active Record class, with all the testability and dishonest API issues that ensue. Both Zend Framework and Doctrine 1.x represent tables as first-class objects. Examples Zend Framework's component Zend_Db, which is explored in the sample code, provides always generic implementations of Zend_Db_Table, and the possibility of optional subclassing (to add domain-specific methods). It is not recommend to expose the API of Table Data Gateway in front-end code, but it's a simple solution when the business logic does not warrant a full-featured Domain Model. Even when working with a Domain Model, and before the introduction of generic Data Mappers for PHP, the Table Data Gateway can be used in a composition solution (wrapped) to craft a simple API for a domain-specific Data Mapper, resulting in decoupling from the database. As I've written earlier, the sample code is taken from the Zend_Db_Table class of Zend Framework (actually from its parent abstract class, Zend_Db_Table_Abstract). I've enriched the docblock comments and left out all the methods not part of the main API (most of getters and setters for configuration and protecte|private members). $value) { switch ($key) { case self::ADAPTER: $this->_setAdapter($value); break; case self::DEFINITION: $this->setDefinition($value); break; case self::DEFINITION_CONFIG_NAME: $this->setDefinitionConfigName($value); break; case self::SCHEMA: $this->_schema = (string) $value; break; case self::NAME: $this->_name = (string) $value; break; case self::PRIMARY: $this->_primary = (array) $value; break; case self::ROW_CLASS: $this->setRowClass($value); break; case self::ROWSET_CLASS: $this->setRowsetClass($value); break; case self::REFERENCE_MAP: $this->setReferences($value); break; case self::DEPENDENT_TABLES: $this->setDependentTables($value); break; case self::METADATA_CACHE: $this->_setMetadataCache($value); break; case self::METADATA_CACHE_IN_CLASS: $this->setMetadataCacheInClass($value); break; case self::SEQUENCE: $this->_setSequence($value); break; default: // ignore unrecognized configuration directive break; } } return $this; } /** * Inserts a new row. * The data structure is as generic as possible. The list of columns is * known by configuration. * $this->_db is a light abstraction over PDO, which already encapsulates * most of the SQL. Database abstraction is not a banal task and segregating * the functionalities in different classes is very helpful. * * @param array $data Column-value pairs. * @return mixed The primary key of the row inserted. */ public function insert(array $data) { $this->_setupPrimaryKey(); /** * Zend_Db_Table assumes that if you have a compound primary key * and one of the columns in the key uses a sequence, * it's the _first_ column in the compound key. */ $primary = (array) $this->_primary; $pkIdentity = $primary[(int)$this->_identity]; /** * If this table uses a database sequence object and the data does not * specify a value, then get the next ID from the sequence and add it * to the row. We assume that only the first column in a compound * primary key takes a value from a sequence. */ if (is_string($this->_sequence) && !isset($data[$pkIdentity])) { $data[$pkIdentity] = $this->_db->nextSequenceId($this->_sequence); } /** * If the primary key can be generated automatically, and no value was * specified in the user-supplied data, then omit it from the tuple. */ if (array_key_exists($pkIdentity, $data) && $data[$pkIdentity] === null) { unset($data[$pkIdentity]); } /** * INSERT the new row. */ $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name; $this->_db->insert($tableSpec, $data); /** * Fetch the most recent ID generated by an auto-increment * or IDENTITY column, unless the user has specified a value, * overriding the auto-increment mechanism. */ if ($this->_sequence === true && !isset($data[$pkIdentity])) { $data[$pkIdentity] = $this->_db->lastInsertId(); } /** * Return the primary key value if the PK is a single column, * else return an associative array of the PK column/value pairs. */ $pkData = array_intersect_key($data, array_flip($primary)); if (count($primary) == 1) { reset($pkData); return current($pkData); } return $pkData; } /** * Updates existing rows. * Again we see generic data structures, not tied to PDO * or to particular adapters. * * @param array $data Column-value pairs. * @param array|string $where An SQL WHERE clause, or an array of SQL WHERE clauses. * @return int The number of rows updated. */ public function update(array $data, $where) { $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name; return $this->_db->update($tableSpec, $data, $where); } /** * Deletes existing rows. * * @param array|string $where SQL WHERE clause(s). * @return int The number of rows deleted. */ public function delete($where) { $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name; return $this->_db->delete($tableSpec, $where); } /** * Fetches rows by primary key. The argument specifies one or more primary * key value(s). To find multiple rows by primary key, the argument must * be an array. * * This method accepts a variable number of arguments. If the table has a * multi-column primary key, the number of arguments must be the same as * the number of columns in the primary key. To find multiple rows in a * table with a multi-column primary key, each argument must be an array * with the same number of elements. * * The find() method always returns a Rowset object, even if only one row * was found. * * @param mixed $key The value(s) of the primary keys. * @return Zend_Db_Table_Rowset_Abstract Row(s) matching the criteria. * @throws Zend_Db_Table_Exception */ public function find() { $this->_setupPrimaryKey(); $args = func_get_args(); $keyNames = array_values((array) $this->_primary); if (count($args) < count($keyNames)) { require_once 'Zend/Db/Table/Exception.php'; throw new Zend_Db_Table_Exception("Too few columns for the primary key"); } if (count($args) > count($keyNames)) { require_once 'Zend/Db/Table/Exception.php'; throw new Zend_Db_Table_Exception("Too many columns for the primary key"); } $whereList = array(); $numberTerms = 0; foreach ($args as $keyPosition => $keyValues) { $keyValuesCount = count($keyValues); // Coerce the values to an array. // Don't simply typecast to array, because the values // might be Zend_Db_Expr objects. if (!is_array($keyValues)) { $keyValues = array($keyValues); } if ($numberTerms == 0) { $numberTerms = $keyValuesCount; } else if ($keyValuesCount != $numberTerms) { require_once 'Zend/Db/Table/Exception.php'; throw new Zend_Db_Table_Exception("Missing value(s) for the primary key"); } $keyValues = array_values($keyValues); for ($i = 0; $i < $keyValuesCount; ++$i) { if (!isset($whereList[$i])) { $whereList[$i] = array(); } $whereList[$i][$keyPosition] = $keyValues[$i]; } } $whereClause = null; if (count($whereList)) { $whereOrTerms = array(); $tableName = $this->_db->quoteTableAs($this->_name, null, true); foreach ($whereList as $keyValueSets) { $whereAndTerms = array(); foreach ($keyValueSets as $keyPosition => $keyValue) { $type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE']; $columnName = $this->_db->quoteIdentifier($keyNames[$keyPosition], true); $whereAndTerms[] = $this->_db->quoteInto( $tableName . '.' . $columnName . ' = ?', $keyValue, $type); } $whereOrTerms[] = '(' . implode(' AND ', $whereAndTerms) . ')'; } $whereClause = '(' . implode(' OR ', $whereOrTerms) . ')'; } // issue ZF-5775 (empty where clause should return empty rowset) if ($whereClause == null) { $rowsetClass = $this->getRowsetClass(); if (!class_exists($rowsetClass)) { require_once 'Zend/Loader.php'; Zend_Loader::loadClass($rowsetClass); } return new $rowsetClass(array('table' => $this, 'rowClass' => $this->getRowClass(), 'stored' => true)); } return $this->fetchAll($whereClause); } /** * Fetches a new blank row (not from the database). * Thanks to the metadata, a new Row Data Gateway can be created. This * if a Factory Method. The dynamic nature of PHP makes configuring the * subclass for the Row Data Gateway as simple as defining a string. * * @param array $data OPTIONAL data to populate in the new row. * @param string $defaultSource OPTIONAL flag to force default values into new row * @return Zend_Db_Table_Row_Abstract */ public function createRow(array $data = array(), $defaultSource = null) { $cols = $this->_getCols(); $defaults = array_combine($cols, array_fill(0, count($cols), null)); // nothing provided at call-time, take the class value if ($defaultSource == null) { $defaultSource = $this->_defaultSource; } if (!in_array($defaultSource, array(self::DEFAULT_CLASS, self::DEFAULT_DB, self::DEFAULT_NONE))) { $defaultSource = self::DEFAULT_NONE; } if ($defaultSource == self::DEFAULT_DB) { foreach ($this->_metadata as $metadataName => $metadata) { if (($metadata['DEFAULT'] != null) && ($metadata['NULLABLE'] !== true || ($metadata['NULLABLE'] === true && isset($this->_defaultValues[$metadataName]) && $this->_defaultValues[$metadataName] === true)) && (!(isset($this->_defaultValues[$metadataName]) && $this->_defaultValues[$metadataName] === false))) { $defaults[$metadataName] = $metadata['DEFAULT']; } } } elseif ($defaultSource == self::DEFAULT_CLASS && $this->_defaultValues) { foreach ($this->_defaultValues as $defaultName => $defaultValue) { if (array_key_exists($defaultName, $defaults)) { $defaults[$defaultName] = $defaultValue; } } } $config = array( 'table' => $this, 'data' => $defaults, 'readOnly' => false, 'stored' => false ); $rowClass = $this->getRowClass(); if (!class_exists($rowClass)) { require_once 'Zend/Loader.php'; Zend_Loader::loadClass($rowClass); } $row = new $rowClass($config); $row->setFromArray($data); return $row; } }
May 5, 2010
by Giorgio Sironi
· 8,011 Views
article thumbnail
Practical PHP Patterns: Service Layer
The last domain logic pattern we will treat in this series is the Service Layer one. In its simplest form, a Service Layer is a set of service classes that deal with application logic, and that are characterized from being used from different front-ends. Source code, at every level of abstraction, is the representation of data entities and their related behavior, particularly in an object-oriented paradigm. There are different types of logic which this behavior can be partitioned into: business logic is encapsulated in a Domain Model, and it is specific to the particular domain the application works in. The added value of an enterprise application ensues primarily from its business logic. application logic is in the scope of a Service Layer, and it is not strictly domain-specific, although its implementation may be. For example, translating objects into an XML or Json representation is part of application logic, even if it is executed with application-specific classes which depends on an underlying Domain Model. The task of representing data in a particular format is oblivious to the domain, as it does not belong to forums or social networks platforms only, or to an electronic or chemistry domain. presentation logic finds in an user interface its quintessence, and it can be considered as the subset of application logic which governs the end user view of the system. I would not consider a difference of format in the whole representation of an object as presentation logic, though, as it falls into the realm of reusability I would want to keep in a Service Layer. Commonly this different concerns of an application are organized in different layers, where each layer resides on the top of the previous one. In classic approaches, there is an infrastructure layer which the business logic layer depends on, and which deals for example with persistence issues. In more evolved approaches, however, keeping the Domain Model as the very core of the application is the most sound choice, moving infrastructure in a Service Layer which can plug in the Domain Model via implementing certain adapter interfaces (like a Repository or a Factory). Thus a Service Layer is particularly useful for example when there are different front-ends to a common Domain Model. These front-ends, such as user interfaces or REST Apis, delegate the application logic to a Service Layer, which encapsulates it. Pushing this logic into the Domain Model would clutter the core of the application, since is is not strictly necessary to work with it. Responsibilities of a Service Layer include, for starters, CRUD functions over objects of the respective Domain Model. Some of these responsibilities may be already included in the Domain Model (Factories for Entities and Value Objects), while other ones are usually only specified as interfaces with the implementations left to an infrastructure Service Layer (Repositories). Example of the latter components are the bread and butter of a Service Layer. Persistence-related actions such as saving objects in a database, data translation (to and from Json, XML, yaml), integration of mail and every service which do not reside in the same PHP execution environment of the Domain Model is a candidate for a class or component in a Service Layer, whose implementations can be stubbed out in acceptance testing. Note that services are also implemented in a Domain Model when they do not contain knowledge which spans outside of the domain and of basic language structures. Generally speaking, services are a point of connection between different Entities and objects, which accomodate operations that would couple the other objects together if implemented directly on them. Only when there are more concerns involved than the execution of logic on domain objects - persistence or orthogonal operations - these services shall be moved to an upper level component like a Service Layer. In some cases, the Service Layer becomes overly generic and orthogonal to the underlying Domain Model, to the point that it is recycled in different applications. Object-relational mappers are part of the infrastructure, and a common example of reusable services. Though, the composition of libraries objects (has-a relationship) is preferable to the direct usage of them, or to their subclassing. Generic frameworks and libraries have a catch-all Api, while a specific Service Layer defines only the use cases actually employed by the front-ends - for example removing the unnecessary update of crucial entities that should be immutable by modelling. Finally, a Service Layer can work without an underlying Domain Model, by interfacing to external web (and non-web) services. If there is local state involved, however, it is difficult to avoid having a basic Domain Model just to define data structures that the Services pass around. The client code, which resides in front-end, has no knowledge of the difference between methods that act over a local Domain Model or an external entity: the Service Layer effectively isolates the upper layer from changes in the lower one. The code sample builds on the sample presented in the Domain Model article, continuing with the idea of an upper level layer. The sample features two service classes, one as a stubbed implementation of an interface of the Domain Model and one that it is employed only at an higher level. setSender('[email protected]'); $mail->setRecipient('[email protected]'); $mail->setSubject('Important stuff'); $mail->setText('I wanted to talk you about...'); return array( $mail ); } } /** * Service that belongs only to the very Service Layer. * It may have an interface, but it will be kept in this layer. */ class EmailTransferService { /** * Transforming an object to XML is a common task for a Service Layer. * However, dependencies towards the Domain Model are well-accepted * but they don't mean that this layer's classes should be * included in the lower layer. * Keeping the XML transformation in one place aids different front-ends * in sharing code. */ public function toXml(Email $mail) { return "\n" . " " . $mail->getSender() . "\n" . " " . $mail->getRecipient() . "\n" . " " . $this->_encode($mail->getSubject()) . "\n" . " " . $this->_encode($mail->getText()) . "\n" . "\n"; } protected function _encode($text) { return htmlentities($text); } } // client code $repository = new DumbEmailRepository(); $transferService = new EmailTransferService(); foreach ($repository->getEmailsFor('[email protected]') as $mail) { echo $transferService->toXml($mail); }
May 2, 2010
by Giorgio Sironi
· 24,508 Views
article thumbnail
Synchronization in PHP
What does synchronization mean We are talking about the process-related synchronization here. Synchronization is the the application of particular mechanisms to ensure that two concurrently-executing processes do not execute specific portions of a program at the same time [Wikipedia]. More in general, the specific portions are the ones that access data structures shared between different processes, and that should not be available to a process while another one is halfway through modifying them, thus keeping the invariants (which processes rely on in their logic) of such data satisfied. For example, different processes can get the value of a common variable, increment it, and save this new value in the original location. If a moderately high number of processes is executed in time-sharing, two or more of them can obtain the value of the variable at the same time, resulting in only one increment for two executions. It is said that this kind of operations on data should be atomic: specific blocks of code should be allowed to run in their entirety before any other portion that touches the same data structure (essentially that modifies the same state) is executed. In PHP A PHP script is inherently immune from internal synchronization issues, unlike other languages, because of its simple architecture. There is no native support for creating multiple threads that share the same PHP variables and that run concurrently in the same PHP script. You can use exec() to run an external program in background or another PHP scripts, but it does not share the scope of the original script (like an include()d file would do) nor this is generally a good idea if not for specific use cases that involve complex integration of external systems. PHP scripts have a short life, and there is usually no need for multiple processes inside of them. Concurrent processes are commonly employed to perform tasks that wait for external resources or computations, so that if one process blocks while expecting a function's return value, other processes can use the cpu time for their own sake. But beware that in PHP, the client waits for the completion of a generated page until the PHP script ends and the control is returned to the HTTP server; if you have business logic that is waiting for external events or resources and you want to return the control to the user in the meantime, you don't need a new thread (which in the current architecture you had to wait, too): you need to outsource this work. Zend Server Job Queue and, more simply, cron let you set up tasks for asynchronous execution. For example you can schedule a PHP script that performs heavy computation and that has to be executed once an hour. In my opinion, this is multithreading as intended in PHP. Outside PHP Even if PHP is shared-nothing by nature and does not present classical race conditions on variables due to its limitations, every kind of shared resource is a candidate for synchronization issues. Since PHP scripts are short-lived and stateless, the resources that maintain state in behalf of PHP scripts are the target of this analysis: different scripts or even the very same script can be executed more than one time, concurrently. Thus, PHP code can interfere with itself as much as Java code does. Sessions are not usually a source of race conditions. Every session is confined to a single client via a cookie used as a key, so you have to consider only the pages and the actions undertaken by a single user at the same time for an analysis of what can go wrong. The biggest issue, though, is the stale of data represented in different views while it is updated in the model, but you have to look in the Ajax world for a workaround due to the nature of the HTTP protocol. Databases, at least the relational ones, guarantee atomicity of operations to a certain extent with the definition of transactions. Databases are the quintessence of application state, and you can take advantage of their ACID properties in a transaction. For example, if you really have to calculate a new key for a table by looking at the already existent ones: SELECT MAX(id) + 1 FROM mytable; INSERT INTO mytable VALUES (4242, 'The name', ...); -- 4242 is the new id UPDATE mytable SET field = ... WHERE id = 4242; at least wrap in a transaction this changeset so that you do not end up updating some other 4242th row which has been inserted by another instance of the PHP script after your SELECT. PDO throws exceptions (unlike mysql_*() functions which often fail silenty), so this example should work anyway when the INSERT fails. But why fail when there is nothing that prevent the row from being inserted with a valid id? This is not the user's fault. You can see the potential for race conditions when doing data-intensive queries in PHP scripts. The file system is not immune from concurrency problems as well; in this case the rows are substituted by files and the primary keys by file names. The best solutions involve using a natural key for the filename, or generating an hash: $filename = uniqid('prefix', true); // second parameter is 'more cool?' Unless two filenames for uploaded files are generated at the same microsecond, the resulting ids should be different. Or, if you're paranoid: mt_srand(); $filename = uniqid(mt_rand(), true); In sum, when you're expecting your applications to run many scripts every second, take your time to check the possibility that race conditions arise.
April 28, 2010
by Giorgio Sironi
· 33,158 Views
article thumbnail
Mediator Pattern Tutorial with Java Examples
Learn the Mediator Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
April 26, 2010
by James Sugrue
· 113,645 Views · 3 Likes
article thumbnail
Practical PHP Patterns: Domain Model
The architectural pattern I'd like to talk about in this article is the overly famous Domain Model. An application's Domain Model is simply defined as an object graph created from domain-specific classes; when present, a Domain Model is the core of the application, where all the business logic resides. This object graph is employed by upper layers of an application which present it to the user. The metaphor for this methodology In software development, the term domain (or business domain) is an umbrella for the area the application is built in, and that it will serve. The new domains we encounter as we move to new projects are one of the most interesting points of software development, where we are constantly embracing new fields and gaining knowledge. Given a domain such as a particular industry (chemical, electronics) or business (air travelling, e-commerce), the point of connection of an application with these activities is its model. A model is an abstract representation of the reality of the domain, which captures its interesting and relevant aspects. The practice of modelling is not a specific trait of software development (in particular model-driven development), but it is a more general scientifical process. For example, everyone who works in the field of information technology knows the voltage/current relationships for simple components such as resistors and capacitors (Ohm's law and current derivative of the voltage). The specific domain here is electronics, and this model is named lumped component model, essentially because it lets a designer connect isolated one-port (two terminals) components to build his desired circuit. This model is a simplification of much more complex models of reality: the Maxwell equations and the propagation of electromagnetic fields; the lumped component model is valid whenever the frequency of the voltage/current signals in the circuit is low, so that the wavelengths of these signals are far greater than the dimensions of the circuit (if that goes over your head, don't worry, it's the field of electrical engineers.) When designers consider larger circuits, such as a transmission line, this model ceases to give correct results and more general ones must be employed. The domain is almost the same, but the model serves a different purpose and has to be necessarily different from the one used in small scale circuits. This complex example is here only to show that given a domain, there is no single model for it, but there are many possible ones which may adapt more or less reliably to the goals of an application. Starting from a modelling phase and deep understanding of the domain are key points of Domain-Driven Design, one of the ascending methodologies for developing complex enterprise software. Software models While there are standard mathematical models for many domains in the scientific world, software developers usually build a tailored one in every different application, performing an analysis of the domain (or at least they should.) The result of the modelling can comprehend document or diagrams, but the most powerful artifact is an executable model. Object-oriented programming is a almost perfect paradigm when it comes to modelling the real world, and lets the developers construct a Domain Model in the form of a set of classes. In a correct implementation of a Domain Model, these classes should be behaviorally complete: they must encapsulate their data as much as possible and expose a set of methods, while avoiding their usage as dumb data containers. The bread and butter of a Domain Model are the classical example of User, Post, Forum, Group, PrivateMessage classes, which are usually in a one to one relationship with database tables. But the Domain Model is not limited to these Entity classes: it also "comprehends" ValueObjects (modelization of domain-specific data types) and various kinds of Services. Every class that encapsulates business logic is welcome, so that this logic is not duplicated in upper layers, which are the primary clients of the Domain Model. Dependencies and purity Another key trait of the classes included in the Domain Model is the absence of external dependencies, like a library to store in the data contained in the objects in a database. The code artifact in a Domain Model are either interfaces, or Plain Old Php Objects (classes which do not extend any external abstract superclass.) Active Record approaches should be avoided because not only a relational database is an infrastructure detail not included in the Domain Model itself, but the very concept of persistence is abstracted away. As far as the clients of the Domain Model are concerned, the state and behavior of the application are represented by an in-memory object graph, whose methods expose functionalities and which client code can play with. There are no dependencies from a Domain Model towards infrastructure classes, because these dependencies must be inverted. The resulting system is an instance of the hexagonal architecture, where the Domain Model defines ports (interfaces) and infrastructure can be chosen to provide adapters for these ports (implementations in the form of classes extraneous to the model). The implementaton of non-invasive persistence is the subject of the Data Mapper pattern, which will be treated later in this series, but every kind of service implementation which communicate with the outside of the core object graph (databases, network, filesystem) is only defined as a contract in the Domain Model. Persistence is almost always dealt with a library in other object-oriented languages, now also in PHP with a non-invasive ORM such as Doctrine 2. Nothing obstructs the developers from implementing a specific Data Mapper by hand, but it's a very repetitive and prone to errors task. While in origin simpler, invasive patterns such as Active Record could be used in a Domain Model, nowadays with Data Mapper availables it is considered an hack. Sample Returning to the subject of the Domain Model as the core of an application, the diffused opinion is that the more complex the business logic and the data involved, the more the application benefits from a rich Domain Model. Thus, this pattern should not be used in small-sized applications where there is no much more logic than CRUD screens for data containers, which unfortunately were a target for PHP in the last ten years. I hope PHP keeps evolving to finally break in the enterprise segment, where this pattern is most valuable. Due to the size and scope of this article, I am forced to keep the sample code short. Forgive me if you think that you can achieve the same functionality with fewer lines of code, but this pattern is about architecture and should highlight the separation of concerns between classes more than the KISS principle. Another problem with code samples in modelling is that you have to actually know the domain well to follow the discussion. For this reason I chose a webmail system for this example. _sender; } /** * Do we need setters and getters? Every field should be * analyzed. If we can keep it private and inaccessible, * it's usually better. */ public function setSender($sender) { $this->_sender = $sender; } /** * @return string */ public function getRecipient() { return $this->_recipient; } public function setRecipient($recipient) { $this->_recipient = $recipient; } /** * @return string */ public function getSubject() { return $this->_subject; } public function setSubject($subject) { $this->_subject = $subject; } /** * @return string */ public function getText() { return $this->_text; } public function setText($text) { $this->_text = $text; } public function __toString() { return $this->_subject . ' > ' . substr($this->_text, 0, 20) . '...'; } public function reply() { $reply = new Email(); $reply->setRecipient($this->_sender); $reply->setSender($this->_recipient); $reply->setSubject('Re: ' . $this->_subject); $reply->setText($this->_sender . " wrote:\n" . $this->_text); return $reply; } } /** * Interface for a service. This is part of the Domain Model, * implementations will be plugged in depending on the environment. */ interface EmailRepository { /** * @return array * @TypeOf(Email) */ public function getEmailsFor($recipient); } // client code $mail = new Email(); $mail->setSender("[email protected]"); $mail->setRecipient("[email protected]"); $mail->setSubject('Hello'); $mail->setText('This is a test of an Email object, which is part of our Domain Model.'); echo $mail, "\n"; $reply = $mail->reply(); echo $reply, "\n";
April 25, 2010
by Giorgio Sironi
· 8,021 Views
article thumbnail
“When a class with type parameters is not a parameterized class” – a Java Generics Puzzler
while recently fiddling with some more runtime generic type extraction for deployit , i was caught out by some unexpected behaviour by the reflection api. a check of the javadocs quickly revealed that i had once again been too hasty in relying on "common sense". still, the case seems sufficiently unintuitive to merit discussion. in this case, the issue centres on the interplay between class.gettypeparameters and parameterizedtype . the gist of the code looks something like: interface spying {} // small class hierarchy class person {} class professional extends person {} class agent extends professional {} class assassin extends professional {} class bystander extends person {} ... person jbond = new agent(); system.out.println("generic superclass type argument: " + trygetsuperclassgenerictypeparam(jbond)); person joepublic = new bystander(); system.out.println("generic superclass type argument: " + trygetsuperclassgenerictypeparam(joepublic)); person oddjob = new assassin(); system.out.println("generic superclass type argument: " + trygetsuperclassgenerictypeparam(oddjob)); ... type trygetsuperclassgenerictypeparam(object obj) { class clazz = obj.getclass(); class superclass = clazz.getsuperclass(); // elvis would be preferred, but for the sake of clarity... if (superclass.gettypeparameters().length > 0) { return ((parameterizedtype) clazz.getgenericsuperclass()).getactualtypearguments()[0]; } else { return null; } } so...what happens? trygetsuperclassgenerictypeparam is where the action happens. it seems fairly straightforward: see if the object's superclass is generic (i.e. takes type parameters) and, if so, cast its type representation to parameterizedtype to extract the actual value for the type parameter. if the superclass is not generic, simply return null. when this code is run, the first two invocations of trygetsuperclassgenerictypeparam result in the expected: generic superclass type argument: interface spying generic superclass type argument: null what about the third one? well, given the fact that we've omitted to specify a generic type parameter for professional we might assume 1 that we'd also get null. the actual output, however, is: exception in thread "main" java.lang.classcastexception: java.lang.class cannot be cast to java.lang.reflect.parameterizedtype at trygetsuperclassgenerictypeparam(...) huh? in order to figure out what's going on here, let's have a look at the javadoc for class.gettypeparameters: returns an array of typevariable objects that represent the type variables declared by the generic declaration represented by this genericdeclaration object, in declaration order. returns an array of length 0 if the underlying generic declaration declares no type variables. in other words, this is returning class-level information about the declaration of, in our case, the professional class, which of course does have a type parameter. however, if we look at class.getgenericsuperclass 2 , which we invoke next, we find that it: returns the type representing the direct superclass of the entity [...] represented by this class. if the superclass is a parameterized type, the type object returned must accurately reflect the actual type parameters used in the source code. here, the information returned is specific to the actual declaration of the class, which may (or may not, as in our case) specify type paramaters for its superclass. and therein lies the problem: professional.class.gettypearguments looks at the declaration of the professional class, discovering a type argument, whereas assassin.class.getgenericsuperclass looks at the occurrence of professional in the declaration of assassin and discovers no type parameters. hence, it returns a class rather than a parameterizedtype and blows up our code. ergo to cut a long story short: if an object's superclass has type arguments as determined by class.gettypearguments that does not mean that object.getclass().getgenericsuperclass() will be a parameterizedtype. footnotes read "i assumed" it's a pity that class.getgenericsignature , which determines the "generic or not" behaviour of class.getgenericsuperclass, is private, native and undocumented. from http://blog.xebia.com/2010/04/22/when-a-class-with-type-parameters-is-not-a-parameterized-class-a-java-generics-puzzler/
April 22, 2010
by Andrew Phillips
· 28,494 Views
article thumbnail
Practical PHP Patterns
April 22, 2010
by Giorgio Sironi
· 6 Views
article thumbnail
Memento Pattern Tutorial with Java Examples
Learn the Memento Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
April 21, 2010
by James Sugrue
· 63,384 Views · 2 Likes
article thumbnail
HTTP verbs in PHP
While PHP is capable of performing HTTP requests towards external servers with any method, either via the HTTP extension or by opening streams directly, the support of the various GET, POST, PUT and other verbs on the receiving side of HTTP requests is a bit more complicated. Background The HTTP 1.0 specification (RFC 1945) officially defined only the GET, HEAD and POST methods, leaving open the possibility of adding extension methods: Method = "GET" ; Section 8.1 | "HEAD" ; Section 8.2 | "POST" ; Section 8.3 | extension-method The specification of HTTP 1.1 (as its last 1999 incarnation RFC 2616) defines explicitly other methods: Method = "OPTIONS" ; Section 9.2 | "GET" ; Section 9.3 | "HEAD" ; Section 9.4 | "POST" ; Section 9.5 | "PUT" ; Section 9.6 | "DELETE" ; Section 9.7 | "TRACE" ; Section 9.8 | "CONNECT" ; Section 9.9 | extension-method Of these methods, the more interesting ones due to their usage in RESTful applications are GET, POST, PUT and DELETE: GET is a safe, idempotent method and it is used to retrieve a resource. POST is considered a catch-all method nowadays, but its intent is defining a subordinate resource to the current one. For instance, posting to a blog resource may create a new post. PUT is the analogue of GET used to send a resource to the HTTP server. DELETE is the analogue of GET used to, of course, delete a particular resource. Client support GET and POST are the bread and butter of requests sent towards PHP applications. They are commonly generated directly by the browser. A GET request is generated by a link or a form with the specified method attribute set as get. A POST request instead is usually obtainable in native HTML 4 only with a form, which may contain also an enctype attribute to set the Content-Type header of the request (usually employed for the upload of files via POST method.) Browsers often limit their support for HTTP request to these two, as the HTML specification does not define a standard mean to generate other type of requests on the client-side. We have a programmatical way of making asynchronous HTTP requests, Javascript, but it does not help either as it's limited by the implementor's capabilities. Javascript libraries do not force particular restrictions of the allowed methods: we may send GET, POST, PUT or DELETE requests to an endpoint on the server, but via an XMLHttpRequest object (which is their standard back-end) the unsupported methods will be emulated via overloaded POST. This means a POST request will be produced with an additional parameter (which may be named _method or _requestType, depending on the particular library) that describes the actual method used in the client. You get to maintain the semantic of the request in the client code, though, and maybe in the future native support for PUT and DELETE request will be available. There are ways to make a real PUT or DELETE request, and they usually require more complex infrastructure on the client, like Java applets or non-standard Javascript (which is not supported in the majority of browsers), or even not using a browser as the client, for instance using a web service acting as a client of another one. Server support But how can we detect the HTTP request method in a PHP script? For the common methods, such as GET and POST, the superglobal arrays $_GET and $_POST are always available and contain the request parameters. You may want to wrap them with an object-oriented interface, and note that in the case of files upload via POST you should also look at the $_FILES superglobal array. For the other methods, the first thing to do is setting up your webserver with a directive that routes all the PUT requests to a single, dynamic entry point. In the case of Apache, this is described in the PHP manual as: Script PUT /put.php The pointed script simply has to read from the standard input the PUT request: $putdata = fopen("php://input", "r"); file_get_contents() won't work here; welcome back to the world of CGI! :) The manual and the user comments are also a valuable resource for common pitfalls in implementing this type of endpoints. With regard to the DELETE requests, the same configuration is valid to route the requests to a single entry point. Then, it's a matter of identifying the right environment variables, which may vary depending on your HTTP server. Fortunately, PHP frameworks do most of the work, and you are free to programmatically implement different behaviors depending on the type of the request.
April 19, 2010
by Giorgio Sironi
· 10,742 Views
article thumbnail
Using Hibernate Validator to Cover Your Validation Needs
Recently I had to choose a validation framework or write one by myself. First I thought, no big deal, validation is not a complicated issue. But the more you think about it, the more you come to the conclusion that it is not as shallow as you think – you need to validate different types, you have different groups and many more issues… In short, writing a validation framework by yourself demands a lot of work. Luckily, JSR 303 solves this and the Hibernate implementation of the JSR does a pretty good job. Hibernate Validator is a JSR 303 implementation for bean validation. The way to work with this framework is first, to define constraints for java bean fields, and then, validating the bean. JSR 303 JSR 303 – defines a metadata model and API for entity validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML. The API is not tied to a specific application tier or programming model. It is specifically not tied to either the web tier or the persistence tier, and is available for both server-side application programming, as well as for rich client Swing application developers. Hibernate Validator features Defining validation data using annotation and/or XML. Full object validation (including inner objects using recursion) Create customized constraints and validators. Customized error messages. Define groups(profiles). Create a Traversable Resolver. Using constraints Using XML Here is a simple example of a constraint using xml: com.mytest 2 In this example the field x can not be null. The field y can not be less than 2. Notice that the “Min” constraint has inner element – “value”. Notice the tag “”. It indicates the root path of all the beans. See also directions on how to load the XML file while using the validator. Using annotations Here is a simple code example: public class MyBean{@NotNullString x;@Min(2)int y;} This example is the equivalent to the previous xml example. Using both Using both annotations and XML constraints is possible. By default if you are using both only the XML is taken, unless you are using the attribute ‘ignore-annotations’ in the XML. Example: com.mytest.beans 2 2 Notice that the attribute ignore-annotations appears twice – for a bean and for a field. The default for a bean is ignore-annotations=”true” – this means that if you have an XML constraint for a bean, it will cancel the attribute constraint, Unless you will indicate that by ignore-annotations=”false” (look at the example). The default for a field is ignore-annotations=”false”. This means that by default annotations for a field are stronger (this is of course after you indicated that that the bean itself wont ignore annotations). If you wont that the XML will be stronger than you have to indicate that by ignore-annotations=”true” (look at the example in the “x2″ constraint). Existing constraints These constraints are a part of the hibernate validation framework: Constraint path Parameters javax.validation.constraints.AssertTrue (none) javax.validation.constraints.AssertFalse (none) javax.validation.constraints.NotNull (none) javax.validation.constraints.Null (none) javax.validation.constraints.Max value(mandatory) javax.validation.constraints.Min value(mandatory) javax.validation.constraints.DecimalMax value(mandatory) javax.validation.constraints.DecimalMin value(mandatory) javax.validation.constraints.Pattern regexp(mandatory) flags(optional) javax.validation.constraints.Past (none) javax.validation.constraints.Future (none) javax.validation.constraints.Size min(optional) max(optional) javax.validation.constraints.Digits integer(mandatory) fraction(mandatory) org.hibernate.constraints.Email (none) org.hibernate.constraints.Length min(optional) max(optional) org.hibernate.constraints.NotEmpty (none) org.hibernate.constraints.Range min(optional) max(optional) Inner objects constraints If you have nested beans (beans which contain other beans) you can easily let the system validate also the inner objects by using the constraint ‘valid’. XML example: com.mytest.beans Annotation example: public class MyBean{@Valid //inner bean to be validated separatelyprivate InnerBean innerBean; public InnerBean getInnerBean() {return innerBean;}public void setInnerBean(InnerBean innerBean) {this.innerBean = innerBean;}public class InnerBean { @NotNullString xx; public String getXx() {return xx;}public void setXx(String xx) {this.xx = xx;} Validating Example of a simple validation: ValidatorFactory factory = Validation.buildDefaultValidatorFactory();Validator validator = factory.getValidator();Set> constraintViolations = validator.validate(bean); Loading a constraints XML file As mentioned, you don’t have to use an XML file for defining constraints, you can just use annotations. But if you do want an XML file, you will have to load the file. Example: Configuration config = Validation.byDefaultProvider().configure();FileInputStream in = new FileInputStream( new File("resources/demo-constraints.xml"));config.addMapping(in);// Building the customized factory// (along with the changed configuration)ValidatorFactory factory = config.buildValidatorFactory();Validator validator = factory.getValidator(); The result The result(as you can see in the example above) is a collection of ConstraintViolation. Each ConstraintViolation holds the problematic field, it’s value and the error message itself. Example of reading the result: Set> constraintViolations = validator.validate(bean);//printing the resultsfor (ConstraintViolation constraintViolation : constraintViolations) {System.out.println(constraintViolation.getPropertyPath() + " -> " +constraintViolation.getMessage());} This object can be easily transformed to a more generic object like ValidationException or CyotaSoapException and so on. Customized constraints and validators If you want to create a new constraint you will have to create the constraint annotation interface and the validator class. Creating the constraint interface Here is a simple constraint example @Target( { METHOD, FIELD, ANNOTATION_TYPE })@Retention(RUNTIME)@Constraint(validatedBy = MyValidator.class)@Documentedpublic @interface MyConstraint{// These next parameters exist in every constraintString message() default "{com.mytest.MyConstraint.message}";Class[] groups() default {};Class[] payload() default {};// These next parameters are added// They are the constraint's attributesString myOptionalValue() default ""; //this parameter has a default valueString myMustValue(); //this parameters need to get input from the user} Notice the @Constraint annotation. It signifies the class that suppose to validates this constraint. Notice the message class member. It holds an error message or, like in this case, an error code. It will later be interpreted as a literal error message. The payload member holds payload objects. These objects carry additional data attached to the constraints that can be fetched when validating. Nested constraints You can also overload constraints very easily. For example, let’s say I want to create a new constraint which also checks that the value is not null. In this case, all I have to do is this: @Target( { METHOD, FIELD, ANNOTATION_TYPE })@Retention(RUNTIME)@Constraint(validatedBy = MyValidator.class)@Documented@NotNullpublic @interface MyConstraint{String message() default "{com.mytest.MyConstraint.message}";Class[] groups() default {};Class[] payload() default {};} In the example, notice the @NotNull annotation. Creating the validator class Here is an example of a simple validator: public class MyValidatorimplements ConstraintValidator {MyConstraint MyConstraint;/** * This function recives the constraint instance * (along with the user values) */public void initialize(MyConstraint MyConstraint) {this.MyConstraint=MyConstraint;}/** * The value is the actual object instance. * */public boolean isValid(String value, ConstraintValidatorContext arg1) { //using input from the userreturn value!=null && value.startsWith(MyConstraint.myMustValue());} The above code shows an example of a validator which validates that the value of the given string starts with a given character. The validator implements the ConstraintValidator interface. Notice that the constraint is given as input to the initialize() function. The value itself is input to the isValid() function Customizing error messages Each error has an error template. The error template is defined in the constraint annotation interface. This error template is later translated into an error message. The actual error message may be defined in 2 places: 1. Inside the constraint deceleration. The error message be defined when defining the constraint, whether it you are using XML or annotations. XML example: x is too small 2 Java example: public class MyBean{@Min(value = 2, message="x is too small")private String x;public String getX() {return x;}public void setX(String x) {this.x = x;} 2. Using a separate properties message. You may want to load a separate properties file containing the error messages according to the error template. loading the messages properties file is done using the validation factory configuration: Configuration config = Validation.byDefaultProvider().configure();// Using a properties file for customized error messagesFileInputStream in = new FileInputStream(new File("resources/messages.properties"));ResourceBundleMessageInterpolator messageInterpolator =new ResourceBundleMessageInterpolator( new PropertyResourceBundle(in));// Setting a messages properties fileconfig.messageInterpolator(messageInterpolator);in = new FileInputStream(new File("resources/demo-constraints.xml"));config.addMapping(in);// Building the customized factory (along with the changed configuration)ValidatorFactory factory = config.buildValidatorFactory();Validator validator = factory.getValidator(); Using groups There may be occasions when you will want to create a single constraint but with different values for different situations. For example, let’s say you want to create a username field and let him a minimum constraint. But, one time it will have minimum of 5 characters and another time it will have minimum of 6 characters. For cases like this you will want to use groups. To do so, you will have to create a group, create constraints for that group and last, validate objects by attaching the group. Please follow the steps below Create a group To create a group you simply create a new interface. example: public interface MyBeanGroup{} Create a constraint for the group XML example: com.mytest.groups.MyBeanGroup Annotations example: public class MyBean{@NotNull(groups = MyBeanGroup.class)private String x; public String getX() {return x;}public void setX(String x) {this.x = x;} Validate an object using the group Set> constraintViolations = validator.validate(bean, MyBeanGroup.class); The default group The default group is javax.validation.groups.Default. If you don’t assign a constraint any group it applies to the default group. If you are validating an object without using any group, it is validated as a part of the default group. Groups inheritance You can also create an group inheritance tree. In this way, if you validate an object using a group it will prefer constraints that are defined to it. But if there are no such constraints, then it will also take the constraints of it’s parents. Example, this is a group which inherits the default group: public interface MyBeanGroupextends javax.validation.groups.Default{} All the constraints that are defined for that group will apply to it. But also all the constraints which do not apply to any group(and by which apply to the default group), will also apply to it, since it exteds the default group. Jar dependency validation-api-1.0.0.GA.jar hibernate-validator-4.0.2.GA slf4j-api-1.4.2.jar slf4j-simple-1.4.2.jar log4j-1.2.15.jar Only for java5 jaxb-xjc-2.1.6.jar jaxb-impl-2.1.6.jar jaxb-api-2.1.jar activation-1.1.jar geronimo-stax-api_1.0_spec-1.0.1.jar References JSR 303 specification- Bean validation Product main page Hibernate Validator documentation Download demo project from http://www.aviyehuda.com/
April 15, 2010
by Avi Yehuda
· 134,466 Views
article thumbnail
Debugging Hibernate Generated SQL
In this article, I will explain how to debug Hibernate’s generated SQL so that unexpected query results be traced faster either to a faulty dataset or a bug in the query. There’s no need to present Hibernate anymore. Yet, for those who lived in a cave for the past years, let’s say that Hibernate is one of the two main ORM frameworks (the second one being TopLink) that dramatically ease database access in Java. One of Hibernate’s main goal is to lessen the amount of SQL you write, to the point that in many cases, you won’t even write one line. However, chances are that one day, Hibernate’s fetching mechanism won’t get you the result you expected and the problems will begin in earnest. From that point and before further investigation, you should determine which is true: either the initial dataset is wrong or the generated query is or both if you’re really unlucky Being able to quickly diagnose the real cause will gain you much time. In order to do this, the greatest step will be viewing the generated SQL: if you can execute it in the right query tool, you could then compare pure SQL results to Hibernate’s results and assert the true cause. There are two solutions for viewing the SQL. Show SQL The first solution is the simplest one. It is part of Hibernate’s configuration and is heavily documented. Just add the following line to your hibernate.cfg.xml file: ... true The previous snippet will likely show something like this in the log: select this_.PER_N_ID as PER1_0_0_, this_.PER_D_BIRTH_DATE as PER2_0_0_, this_.PER_T_FIRST_NAME as PER3_0_0_, this_.PER_T_LAST_NAME as PER4_0_0_ from T_PERSON this_ Not very readable but enough to copy/paste in your favourite query tool. The main drawback of this is that if the query has parameters, they will display as ? and won’t show their values, like in the following output: select this_.PER_N_ID as PER1_0_0_, this_.PER_D_BIRTH_DATE as PER2_0_0_, this_.PER_T_FIRST_NAME as PER3_0_0_, this_.PER_T_LAST_NAME as PER4_0_0_ from T_PERSON this_ where (this_.PER_D_BIRTH_DATE=? and this_.PER_T_FIRST_NAME=? and this_.PER_T_LAST_NAME=?) If they’re are too many parameters, you’re in for a world of pain and replacing each parameter with its value will take too much time. Yet, IMHO, this simple configuration should be enabled in all environments (save production), since it can easily be turned off. Proxy driver The second solution is more intrusive and involves a third party product but is way more powerful. It consists of putting a proxy driver between JDBC and the real driver so that all generated SQL will be logged. It is compatible with all ORM solutions that rely on the JDBC/driver architecture. P6Spy is a driver that does just that. Despite its age (the last release dates from 2003), it is not obsolete and server our purpose just fine. It consists of the proxy driver itself and a properties configuration file (spy.properties), that both should be present on the classpath. In order to leverage P6Spy feature, the only thing you have to do is to tell Hibernate to use a specific driver: com.p6spy.engine.spy.P6SpyDriver ... This is a minimal spy.properties: module.log=com.p6spy.engine.logging.P6LogFactory realdriver=org.hsqldb.jdbcDriver autoflush=true excludecategories=debug,info,batch,result appender=com.p6spy.engine.logging.appender.StdoutLogger Notice the realdriver parameter so that P6Spy knows where to redirect the calls. With just these, the above output becomes: 1270906515233|3|0|statement|select this_.PER_N_ID as PER1_0_0_, this_.PER_D_BIRTH_DATE as PER2_0_0_, this_.PER_T_FIRST_NAME as PER3_0_0_, this_.PER_T_LAST_NAME as PER4_0_0_ from T_PERSON this_ where (this_.PER_D_BIRTH_DATE=? and this_.PER_T_FIRST_NAME=? and this_.PER_T_LAST_NAME=?)|select this_.PER_N_ID as PER1_0_0_, this_.PER_D_BIRTH_DATE as PER2_0_0_, this_.PER_T_FIRST_NAME as PER3_0_0_, this_.PER_T_LAST_NAME as PER4_0_0_ from T_PERSON this_ where (this_.PER_D_BIRTH_DATE=’2010-04-10′ and this_.PER_T_FIRST_NAME=’Johnny’ and this_.PER_T_LAST_NAME=’Be Good’) Of course, the configuration can go further. For example, P6Spy knows how to redirect the logs to a file, or to Log4J (it currently misses a SLF4J adapter but anyone could code one easily). If you need to use P6Spy in an application server, the configuration should be done on the application server itself, at the datasource level. In that case, every single use of this datasource will be traced, be it from Hibernate, TopLink, iBatis or plain old JDBC. In Tomcat, for example, put spy.properties in common/classes and update the datasource configuration to use P6Spy driver. The source code for this article can be found here. To go further: P6Spy official site Log4jdbc, a Google Code contender that aims to offer the same features From http://blog.frankel.ch/debugging-hibernate-generated-sql
April 13, 2010
by Nicolas Fränkel
· 30,826 Views
article thumbnail
Prototype Pattern Tutorial with Java Examples
Learn the Prototype Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
April 9, 2010
by James Sugrue
· 90,920 Views · 14 Likes
article thumbnail
Create Windows 7 start menu using CSS3 only
I am fascinated with how much you can do with so little using CSS3. Many user interface elements that require images in order to have appropriate visual appearance now can be styled only with CSS3. In order to prove that I assigned myself a task to create Windows 7 start menu only with CSS3 (and some icons). If we decompose the menu we'll get one div, two unordered lists with a couple of links each and a few icons. Let's see how each one of those is styled. Demo - Source Container The container named startmenu holds two unordered lists that act as menus. It has linear gradient with three color stops: light blue at the top, dark blue in the middle, and another shade of light blue at the bottom. Transparency is achieved using rgba() which has four parameters. The first three represent red, green and blue color values and the last one is opacity. Two borders are created with border and box-shadow properties. #startmenu { border:solid 1px #102a3e; overflow:visible; display:inline-block; margin:60px 0 0 20px; -moz-border-radius:5px;-webkit-border-radius:5px; position:relative; box-shadow: inset 0 0 1px #fff; -moz-box-shadow: inset 0 0 1px #fff; -webkit-box-shadow: inset 0 0 1px #fff; background-color:#619bb9; background: -moz-linear-gradient(top, rgba(50, 123, 165, 0.75), rgba(46, 75, 90, 0.75) 50%, rgba(92, 176, 220, 0.75)); background: -webkit-gradient(linear, center top, center bottom, from(#327aa4),color-stop(45%, #2e4b5a), to(#5cb0dc)); } Programs menu This unordered list has white background and two borders created with border and box-shadow properties. Its links, which contain icons and program names, uses gradients and box shadows in hover state. #programs, #links {float:left; display:block; padding:0; list-style:none;} #programs { background:#fff; border:solid 1px #365167; margin:7px 0 7px 7px; box-shadow: 0 0 1px #fff; -moz-box-shadow: 0 0 1px #fff; -webkit-box-shadow: 0 0 1px #fff; -moz-border-radius:3px;-webkit-border-radius:3px;} #programs a { border:solid 1px transparent; display:block; padding:3px; margin:3px; color:#4b4b4b; text-decoration:none; min-width:220px;} #programs a:hover {border:solid 1px #7da2ce; -moz-border-radius:3px; -webkit-border-radius:3px; box-shadow: inset 0 0 1px #fff; -moz-box-shadow: inset 0 0 1px #fff; -webkit-box-shadow: inset 0 0 1px #fff; background-color:#cfe3fd; background: -moz-linear-gradient(top, #dcebfd, #c2dcfd); background: -webkit-gradient(linear, center top, center bottom, from(#dcebfd), to(#c2dcfd));} #programs a img {border:0; vertical-align:middle; margin:0 5px 0 0;} Links menu As in the previous case, links menu is quite simple. But the interesting part comes in hover state. Each link has horizontal gradient with three stops: dark blue on the left and right side, and a bit lighter blue in the middle. Now, unlike programs menu links, here, every links has inner element which contains text. This span element has one more gradient - vertical linear gradient. It is transparent in the upper half and the lower part goes from very dark blue to almost transparent light blue. The combination of two transparent gradients gives exactly the same look as buttons in Windows 7 link menu. #links {margin:7px; margin-top:-30px;} #links li.icon {text-align:center;} #links a {border:solid 1px transparent; display:block; margin:5px 0; position:relative; color:#fff; text-decoration:none; min-width:120px;} #links a:hover {border:solid 1px #000; -moz-border-radius:3px; -webkit-border-radius:3px; box-shadow: 0 0 1px #fff; -moz-box-shadow: inset 0 0 1px #fff; -webkit-box-shadow: inset 0 0 1px #fff; background-color:#658da0; background: -moz-linear-gradient(center left, rgba(81,115,132,0.55), rgba(121,163,184,0.55) 50%, rgba(81,115,132,0.55)); background: -webkit-gradient(linear, 0% 100%, 100% 100%, from(#517384), color-stop(50%, #79a3b8), to(#517384)); } #links a span { padding:5px; display:block; } #links a:hover span { background: -moz-linear-gradient(center top, transparent, transparent 49%, rgba(2,37,58,0.5) 50%, rgba(63,111,135,0.5)); background: -webkit-gradient(linear, center top, center bottom, from(transparent), color-stop(49%, transparent), color-stop(50%, rgba(2,37,58,0.5)), to(rgba(63,111,135,0.5))); } Here is the preview, but I suggest you to check out the demo. You can play with backgrounds and see how transparency works. The code works fine in Firefox 3.6+, Safari and Chrome. It degrades gracefully in Opera and IE. I guess I could optimize it a bit so if you have any suggestions please let me know.
April 7, 2010
by Janko Jovanovic
· 9,013 Views
article thumbnail
Converting PDF to HTML Using PDFBox
Over the past few days, while working on another project, I needed to covert PDF documents into HTML. I did the usual searches for tools, but as I'm sure you'll have noticed, the tools available don't get great results. But then, seeing as I'm a software developer, I decided to see if I could program it myself. My requirements were quite simple: get the text out of the document, with the aim of HTML output, and extract the images at the same time. My first port of call was iText, as it was a library that I was already familiar with. iText is great for creating documents, and I was able to get some text out, but the image extraction wasn't really working out for me. The following is a code snippet that I was using to get the images from the PDFs in iText, based on a post on the iText mailing list. But when I used it, none of the images I generated were right - mostly just the box outlines/borders of the images in the PDF. I presume I was doing something wrong. PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\test.pdf"))); for(int i =0; i < reader.getXrefSize(); i++) { PdfObject pdfobj = reader.getPdfObject(i); if(pdfobj != null) { if (!pdfobj.isStream()) { //throw new Exception("Not a stream"); } else { PdfStream stream = (PdfStream) pdfobj; PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE); if (pdfsubtype == null) { // throw new Exception("Not an image stream"); } else { if (!pdfsubtype.toString().equals(PdfName.IMAGE.toString())) { //throw new Exception("Not an image stream"); } else { // now you have a PDF stream object with an image byte[] img = PdfReader.getStreamBytesRaw((PRStream) stream); // but you don't know anything about the image format. // you'll have to get info from the stream dictionary System.out.println("----img ------"); System.out.println("height:" + stream.get(PdfName.HEIGHT)); System.out.println("width:" + stream.get(PdfName.WIDTH)); int height = new Integer(stream.get(PdfName.HEIGHT).toString()).intValue(); int width = new Integer(stream.get(PdfName.WIDTH).toString()).intValue(); System.out.println("bitspercomponent:" + stream.get(PdfName.BITSPERCOMPONENT)); java.awt.Image image = Toolkit.getDefaultToolkit().createImage(img); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = bi.createGraphics(); ImageIO.write(bi, "PNG",new File("C:\\images\\"+ i + ".png")); } } } // ... // // or you could try making a java.awt.Image from the array: // j } } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); } As I was low on time, I moved onto PDFBox which looked like it had already considered my use cases. I got the latest source code from SVN and tried the org.apache.pdfbox.ExtractText class straight away. This allows you to specify a -html flag instead of using the default text output. I ran into an exception straight away. After some debugging I found that what I had downloaded was missing the resources/glyphlist.txt file. I found a copy on the Adobe site and was able to run the utility then. One other thing to note while using these utilities is that you'll need to have ICU4J, iText and the Apache Commons Logging libraries on your build path. The good news was that the utility got all the text out and put it into a HTML format. But the generated HTML wasn't that pretty. Each line that it read got terminated with a , admittedly, an easy thing to change around. Moving onto image extraction, I tried out org.apache.pdfbox.ExtractImages. This class worked perfectly, saving all the images in the PDF as jpeg. I did make one alteration to PDXObjectImage.write2file so that I put the images in a particular folder. The PDFBox utilities really impressed me, as I wasn't sure if it was possible to get this information out of the PDF so easily. All the pieces are there for one single utility that would generate better HTML for you along with the images. As far as I know, no solution exists to do all of this in Java (if I'm wrong, please let me know in the comments section). Have any of the readers tried to achieve this process using iText, PDFBox or any other Java library?
April 7, 2010
by James Sugrue
· 93,894 Views · 2 Likes
article thumbnail
Template Method Pattern Tutorial with Java Examples
Learn the Template Method Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
April 6, 2010
by James Sugrue
· 150,623 Views · 11 Likes
article thumbnail
Python Script For Sending Free Sms Using Way2sms.com
#!/usr/bin/python __author__ = """ NAME: Abhijeet Rastogi (shadyabhi) Profile: http://www.google.com/profiles/abhijeet.1989 """ import cookielib import urllib2 from getpass import getpass import sys from urllib import urlencode from getopt import getopt username = None passwd = None message = None number = None def Usage(): print '\t-h, --help: View help' print '\t-u, --username: Username' print '\t-p, --password: Password' print '\t-n, --number: numbber to send the sms' print '\t-m, --message: Message to send' sys.exit(1) opts, args = getopt(sys.argv[1:], 'u:p:m:n:h',["username=","password=","message=","number=","help"]) for o,v in opts: if o in ("-h", "--help"): Usage() elif o in ("-u", "--username"): username = v ask_username = False elif o in ("-p", "--password"): passwd = v ask_password = False elif o in ("-m", "--message"): message = v ask_message = False elif o in ("-n", "--number"): number = v ask_number = False #Credentials taken here if username is None: username = raw_input("Enter USERNAME: ") if passwd is None: passwd = getpass() if message is None: message = raw_input("Enter Message: ") if number is None: number = raw_input("Enter Mobile number: ") #Logging into the SMS Site url = 'http://wwwb.way2sms.com//auth.cl' data = 'username='+username+'&password='+passwd+'&Submit=Sign+in' #Remember, Cookies are to be handled cj = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) # To fool way2sms as if a Web browser is visiting the site opener.addheaders = [('User-Agent','Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091020 Ubuntu/9.10 (karmic) Firefox/3.5.3 GTB7.0')] try: usock = opener.open(url, data) except IOError: print "Check your internet connection" sys.exit(1) #urlencode performed.. Because it was done by the site as i checked through HTTP headers message = urlencode({'message':message}) message = message[message.find("=")+1:] #SMS sending send_sms_url = 'http://wwwb.way2sms.com//FirstServletsms?custid=' send_sms_data = 'custid=undefined&HiddenAction=instantsms&Action=custfrom950000&login=&pass=&MobNo='+number+'&textArea='+message opener.addheaders = [('Referer','http://wwwb.way2sms.com//jsp/InstantSMS.jsp?val=0')] try: sms_sent_page = opener.open(send_sms_url,send_sms_data) except IOError: print "Check your internet connection( while sending sms)" sys.exit(1) print "SMS sent!!!"
April 4, 2010
by Snippets Manager
· 16,020 Views · 1 Like
article thumbnail
Command Pattern Tutorial with Java Examples
Learn the Command Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
April 2, 2010
by James Sugrue
· 312,343 Views · 21 Likes
article thumbnail
Complete List of Macro Keywords for the NetBeans Java Editor
In NetBeans IDE's Java editor, you can create macros by clicking the "Start Macro Recording" button, performing some actions you'd like to record, then clicking the "Stop Macro Recording" button. The Macro Editor then pops up and you can finetune the macro and also assign a keyboard shortcut to it. (You can also edit macros in the Options window, in the Editor | Macros tab.) A special macro syntax is used to define these macros. For example, if you want to clear the current line in the editor from the cursor, your macro definition would be as follows: selection-end-line remove-selection Then you could assign "Ctrl+L" as the keyboard shortcut for this macro. Whenever you'd then press that key combination, the whole line, from the position of the cursor, would be deleted. But the only way for the syntax to be useful is for it to be made publicly available. I've seen in various places on-line that people are complaining about a lack of documentation in this area. I asked the developers from the NetBeans Java editor team and their advice was: "it should not be that hard to create an action, which will get EditorKit from the JEditorPane in an opened editor, call EK.getActions() and dump Action.NAME property of each action to System.out". That's what I did (together with Action.SHORT_DESCRIPTION) and here is the result: abbrev-debug-line -- Debug Filename and Line Number adjust-caret-bottom -- Move Insertion Point to Bottom adjust-caret-center -- Move Insertion Point to Center adjust-caret-top -- Move Insertion Point to Top adjust-window-bottom -- Scroll Insertion Point to Bottom adjust-window-center -- Scroll Insertion Point to Center adjust-window-top -- Scroll Insertion Point to Top all-completion-show -- Show All Code Completion Popup annotations-cycling -- Annotations Cycling beep -- Beep build-popup-menu -- Build Popup Menu build-tool-tip -- Build Tool Tip caret-backward -- Insertion Point Backward caret-begin -- Insertion Point to Beginning of Document caret-begin-line -- Insertion Point to Beginning of Text on Line caret-begin-word -- Insertion Point to Beginning of Word caret-down -- Insertion Point Down caret-end -- Insertion Point to End of Document caret-end-line -- Insertion Point to End of Line caret-end-word -- Insertion Point to End of Word caret-forward -- Insertion Point Forward caret-line-first-column -- Insertion Point to Beginning of Line caret-next-word -- caret-next-word caret-previous-word -- caret-previous-word caret-up -- Insertion Point Up collapse-all-code-block-folds -- Collapse All Java Code collapse-all-folds -- Collapse All collapse-all-javadoc-folds -- Collapse All Javadoc collapse-fold -- Collapse Fold comment -- Comment complete-line -- Complete Line complete-line-newline -- Complete Line and Create New Line completion-show -- Show Code Completion Popup copy-selection-else-line-down -- Copy Selection else Line down copy-selection-else-line-up -- Copy Selection else Line up copy-to-clipboard -- Copy cut-to-clipboard -- Cut cut-to-line-begin -- Cut from Insertion Point to Line Begining cut-to-line-end -- Cut from Insertion Point to Line End default-typed -- Default Typed delete-next -- Delete Next Character delete-previous -- Delete Previous Character documentation-show -- Show Documentation Popup dump-view-hierarchy -- Dump View Hierarchy expand-all-code-block-folds -- Expand All Java Code expand-all-folds -- Expand All expand-all-javadoc-folds -- Expand All Javadoc expand-fold -- Expand Fold fast-import -- Fast Import find-next -- Find Next Occurrence find-previous -- Find Previous Occurrence find-selection -- Find Selection first-non-white -- Go to First Non-whitespace Char fix-imports -- Fix Imports format -- Format generate-code -- Insert Code generate-fold-popup -- Generate Fold Popup generate-goto-popup -- Generate Goto Popup generate-gutter-popup -- Margin goto -- Go to Line... goto-declaration -- Go to Declaration goto-help -- Go to Javadoc goto-implementation -- Go to Implementation goto-source -- Go to Source goto-super-implementation -- Go to Super Implementation in-place-refactoring -- Instant Rename incremental-search-backward -- Incremental Search Backward incremental-search-forward -- Incremental Search Forward insert-break -- Insert Newline insert-date-time -- Insert Current Date and Time insert-tab -- Insert Tab introduce-constant -- Introduce Constant... introduce-field -- Introduce Field... introduce-method -- Introduce Method... introduce-variable -- Introduce Variable... java-next-marked-occurrence -- Navigate to Next Occurrence java-prev-marked-occurrence -- Navigate to Previous Occurrence jump-list-last-edit -- Last edit jump-list-next -- Forward jump-list-prev -- Back last-non-white -- Go to Last Non-whitespace Char make-getter -- Replace Variable With its Getter make-is -- Replace Variable With its is* Method make-setter -- Replace Variable With its Setter match-brace -- Insertion Point to Matching Brace move-selection-else-line-down -- Move Selection else Line down move-selection-else-line-up -- Move Selection else Line up org.openide.actions.PopupAction -- Show Popup Menu page-down -- Page Down page-up -- Page Up paste-formated -- Paste Formatted paste-from-clipboard -- Paste redo -- Redo reindent-line -- Re-indent Current Line or Selection remove-line -- Delete Line remove-line-begin -- Delete Preceding Characters in Line remove-selection -- Delete Selection remove-tab -- Delete Tab remove-trailing-spaces -- Remove Trailing Spaces remove-word-next -- remove-word-next remove-word-previous -- remove-word-previous replace -- Replace run-macro -- Run Macro scroll-down -- Scroll Down scroll-up -- Scroll Up select-all -- Select All select-element-next -- Select Next Element select-element-previous -- Select Previous Element select-identifier -- Select Identifier select-line -- Select Line select-next-parameter -- Select Next Parameter select-word -- Select Word selection-backward -- Extend Selection Backward selection-begin -- Extend Selection to Beginning of Document selection-begin-line -- Extend Selection to Beginning of Text on Line selection-begin-word -- Extend Selection to Beginning of Word selection-down -- Extend Selection Down selection-end -- Extend Selection to End of Document selection-end-line -- Extend Selection to End of Line selection-end-word -- Extend Selection to End of Word selection-first-non-white -- Extend Selection to First Non-whitespace Char selection-forward -- Extend Selection Forward selection-last-non-white -- Extend Selection to Last Non-whitespace Char selection-line-first-column -- Extend Selection to Beginning of Line selection-match-brace -- Extend Selection to Matching Brace selection-next-word -- selection-next-word selection-page-down -- Extend Selection to Next Page selection-page-up -- Extend Selection to Previous Page selection-previous-word -- selection-previous-word selection-up -- Extend Selection Up shift-line-left -- Shift Line Left shift-line-right -- Shift Line Right split-line -- Split Line start-macro-recording -- Start Macro Recording start-new-line -- Start New Line stop-macro-recording -- Stop Macro Recording switch-case -- Switch Case to-lower-case -- To Lowercase to-upper-case -- To Uppercase toggle-case-identifier-begin -- Switch Capitalization of Identifier toggle-comment -- Toggle Comment toggle-highlight-search -- Toggle Highlight Search toggle-line-numbers -- Toggle Line Numbers toggle-non-printable-characters -- Toggle Non-printable Characters toggle-toolbar -- Toggle Toolbar toggle-typing-mode -- Toggle Typing Mode tooltip-show -- Show Code Completion Tip Popup uncomment -- Uncomment undo -- Undo word-match-next -- Next Matching Word word-match-prev -- Previous Matching Word Now that this list is public, I am looking forward to many new and interesting (and useful) macros being published (maybe even here on NetBeans Zone).
March 31, 2010
by Geertjan Wielenga
· 21,140 Views
article thumbnail
Chain of Responsibility Pattern Tutorial with Java Examples
Learn the Chain of Responsibility Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
March 30, 2010
by James Sugrue
· 161,832 Views · 4 Likes
article thumbnail
How to Rotate Tomcat catalina.out
Avoid a crash and failure to start in tomcat through auto rotation of catalina.out on a linux/unix machine.
March 25, 2010
by Vineet Manohar
· 407,568 Views · 11 Likes
  • Previous
  • ...
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×