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

How-To Tutorials

7018 Articles
article-image-exchange-server-2010-windows-powershell-mailboxes-and-reports
Packt
22 Jul 2011
11 min read
Save for later

Exchange Server 2010 Windows PowerShell: Mailboxes and Reports

Packt
22 Jul 2011
11 min read
The concept of the mailbox is the core feature of any Exchange solution, and it's likely that almost everything you do as Exchange administrator will revolve around this component. Change 2010 SP1 includes several new cmdlets that make life much easier for any Exchange administrator, allowing you to do just about anything you can think of when it comes to managing mailboxes through scripts and one-liners. This includes tasks such as moving, importing, exporting, removing, and reconnecting mailboxes, just to name a few. Read more:  Troubleshooting Mailboxes  Managing Mailboxes Performing some basic steps To work with the code samples in this article, follow these steps to launch the Exchange Management Shell: Log onto a workstation or server with the Exchange Management Tools installed. Open the Exchange Management Shell by clicking on Start | All Programs | Exchange Server 2010. Click on the Exchange Management Shell shortcut. Reporting on the mailbox size Using cmdlets from both the Exchange Management Shell and Windows PowerShell gives us the ability to generate detailed reports. In this recipe, we will use these cmdlets to report on all of the mailboxes within an organization and their total size. How to do it... Use the following one-liner to generate a report of each mailbox in the organization and the total mailbox size: Get-MailboxDatabase | Get-MailboxStatistics | ?{!$_.DisconnectDate} | Select-Object DisplayName,TotalItemSize Pipe the command even further to export the report to a CSV file that can be opened and formatted in Excel: Get-MailboxDatabase | Get-MailboxStatistics | ?{!$_.DisconnectDate} | Select-Object DisplayName,TotalItemSize | Export-CSV c:mbreport.csv -NoType How it works... In both commands, we're using the Get-MailboxDatabase cmdlet to pipe each database in the organization to the Get-MailboxStatistics cmdlet . Notice that in the next stage of the pipeline we are filtering on the DisconnectDate propert y. Inside the filter we are using the exclamation (!) character, which is a shortcut for the -not operator in PowerShell. So we are basically saying, give me all the mailboxes in the organization that are not in a disconnected state. This can be standard mailboxes as well as archive mailboxes. We then select the DisplayName and TotalItemSize properties that give us the name and total mailbox size of each mailbox. There's more... When using the first example to view the mailboxes and their total size, you will see the output in the shell is similar to the following screenshot: Here you can see that we get the total size in megabytes as well as in bytes. If you find that this additional information is not useful, you can extend the previous one-liner using a calculated property: Get-MailboxDatabase | Get-MailboxStatistics | ?{!$_.DisconnectDate} | Select-Object DisplayName, @{n="SizeMB";e={$_.TotalItemSize.value.ToMb()}} | Sort-Object SizeMB -Desc Running the preceding one-liner will provide output similar to the following: Notice that we now have a custom property called SizeMB that reports only the mailbox size in megabytes. We have also sorted this property in descending order and the mailboxes are now listed from largest to smallest. You can continue to pipe this command down to the Export-CSV cmdlet to generate a report that can be viewed outside of the shell. Working with move requests and performing mailbox moves Even if you performed mailbox moves with PowerShell in Exchange 2007, it's important that you understand that the process is completely different in Exchange 2010 SP1. There is a new set of cmdlets available for performing and managing mailbox moves, and the previously-used Move-Mailbox cmdlet no longer exists. The architecture used by Exchange to perform mailbox moves uses a new concept known as move requests, which have been implemented in this latest version. In this recipe, you will learn how to manage move requests from the Exchange Management Shell. How to do it... To create a move request and move a mailbox to another database within the Exchange organization, use the New-MoveRequest cmdlet, as shown next: New-MoveRequest -Identity testuser -TargetDatabase DB2 How it works... Mailbox moves are performed asynchronously with this new method and, unlike using the Move-Mailbox cmdlet in Exchange 2007, the New-MoveRequest cmdlet d oes not perform the actual mailbox move. Mailbox moves are handled by Client Access Servers (CAS) that run the Mailbox Replication Service (MRS). This is a major improvement because mailbox data does not move through an administrative workstation when performing a move; instead, the CAS servers are responsible for transferring the data from one database to another. Not only does this make mailbox moves faster, but it also allows you to kick off one or more mailbox moves from any machine in the organization. You can later check on the status of those move requests from any other machine with PowerShell or the Exchange Management Tools installed. When you create a new move request with the New-MoveRequest cmdlet, the command places a special message in the target mailbox database's system mailbox. The MRS scans the system mailboxes on a regular basis looking for queued mailbox move requests and, once they are found, the MRS will start the move process. Once the move has been completed, a record of the mailbox move is saved and can be viewed using the Get-MoveRequest cmdlet. This recipe only covers local move requests that are performed within an Exchange organization. It is possible to use the New-MoveRequest cmdlet t o perform a mailbox move across Active Directory forest boundaries. For more details, see Managing Remote Move Requests on TechNet at the following URL: http://technet.microsoft.com/en-us/library/ff841978.aspx. If you will be automating mailbox moves using the Exchange Management Shell, it is likely that you will be doing so in bulk. The following example shows how you can move all of the mailboxes from one database to another: Get-Mailbox -Database DB1 | New-MoveRequest -TargetDatabase DB2 In this example, we are retrieving all of the mailboxes in the DB1 database and creating a new move request for each one that will then be moved to the target database of DB2. The -TargetDatabase parameter is actually an optional parameter. If you have multiple mailbox databases in your organization, you can omit the -TargetDatabase parameter in the previous command, and the mailboxes will be moved evenly across the available mailbox databases, as long as those databases have not been suspended or excluded from provisioning and as long as the Mailbox Resources Management Agent is enabled, which is the default setting. There's more... In order to view detailed information about move requests, you can use the Get-MoveRequestStatistics cmdlet. This will return a great deal of useful information for a given move request such as the move status, percent complete, the total bytes transferred, and more. You can also use the -IncludeReport, switch parameter when running the cmdlet to provide a debug level details for mailbox moves. This can be very beneficial when troubleshooting an issue. One of the greatest uses of this cmdlet is reporting on the current status of mailbox moves in progress, especially during large migrations. The following one-liner can be used to gather the statistics for the currently-running mailbox moves and can be run periodically throughout the migration to check the status: Get-MoveRequest | ?{$_.Status -ne ‘Completed’} | Get-MoveRequestStatistics | select DisplayName,PercentComplete,BytesTransferred The preceding command would produce an output for each mailbox similar to the following screenshot: In this example, we're selecting just a few of the properties from the output of the command. Alternatively, it may be useful to export this information to a CSV file or to mail the results to an administrator mailbox. Either way, it gives you a method for monitoring the status of your mailbox moves interactively in the shell or through an automated script. If you just want to do some basic interactive monitoring from the shell to determine when all moves are complete, you can use the following code: while($true) { Get-MoveRequest| ?{$_.Status -ne 'Completed'} Start-Sleep 5 Clear-Host } The output from this command will give you a view of all the incomplete move requests and will refresh every five seconds. This is done by using an endless while loop th at runs Get-MoveRequest, waits for five seconds, clears the screen, and starts over again. Once all moves are completed, just press Ctrl + C to break out of the loop. Removing the move requests You cannot perform a move request for a mailbox if there is an existing move request associated with that mailbox. This is true regardless of the move request status, whether it is complete, pending, cancelled, or failed. You can use the Remove-MoveRequest to delete an existing move request for a single mailbox, using the following syntax: Remove-MoveRequest -Identity testuser -Confirm:$false If you perform frequent moves you may find it necessary to regularly delete all existing move requests in the organization. To do this, use the following command: Get-MoveRequest -ResultSize Unlimited | Remove-MoveRequest -Confirm:$false Keep in mind that stored move requests can provide detailed information that can be used for monitoring or generating reports for mailbox moves. Make sure you no longer need this information before removing these move requests from your organization. Moving the archive mailboxes Consider the following example. The testuser account has a mailbox in the DB1 database, and also a personal archive mailbox in the DB1 database. We can use the following command to move testuser to DB2: New-MoveRequest testuser -TargetDatabase DB2 In this case, both the primary mailbox and the archive mailbox will be moved to DB2. We can customize this behaviour by using some additional parameters made available by the New-MoveRequest cmdlet. For example, if we wanted to only move this user's primary mailbox and leave the archive mailbox in its current location, we could use the following command: New-MoveRequest testuser -TargetDatabase DB2 -PrimaryOnly This command adds the -PrimaryOnly switch parameter, w hich will indicate to the New-MoveRequest cmdlet th at we do not want to move the archive mailbox but we do want to move the primary mailbox to the DB2 database. Use the following command to move only the archive mailbox: New-MoveRequest testuser -ArchiveOnly -ArchiveTargetDatabase DB2 This time, we have added the -ArchiveOnly switch parameter so that only the archive mailbox will be moved. The -ArchiveTargetDatabase is also used to specify that we want to move the archive mailbox to the DB2 database. Moving the mailboxes in batches When performing migrations or moving multiple mailboxes in bulk, it can be useful to move them in batches. The New-MoveRequest cmdlet pr ovides a -BatchName parameter to group multiple mailbox moves into a single, logical collection. Let's say that we are migrating multiple mailboxes to several different databases and we want to easily track the mailbox moves based on a certain criteria: $mailboxes = Get-Mailbox ` -RecipientTypeDetails UserMailbox ` -Database DB1 | Get-MailboxStatistics | ?{$_.TotalItemSize -gt 2gb} $mailboxes | %{ New-MoveRequest -Identity $_.DisplayName ` -BatchName 'Large Mailboxes' ` -TargetDatabase DB2 } Here we are retrieving all mailboxes in the DB1 database that are larger than two gigabytes and storing the results in the $mailboxes variable. We then pipe the $mailboxes object to the ForEach-Object cmdlet (u sing the % alias) and loop through each item. As each mailbox in the collection is processed within the loop, we create a new move request for that mailbox, indicating that it should be included in the Large Mailboxes batch and moved to the DB2 database. At this point, we can easily track the moves in the batch using a simple one-liner: Get-MoveRequest -BatchName 'Large Mailboxes' The preceding command will return each move request included in the Large Mailboxes batch and will provide several details including the display name, move status, and target database. Moving mailboxes with corrupt items When migrating from a previous version of Exchange, or when migrating large mailboxes, it's not uncommon to run into problems with users that have corrupted items in their mailbox. You can use the -BadItemLimit parameter to specify the acceptable number of corrupt, or "bad", items to skip when performing a mailbox move. Keep in mind that if you set the -BadItemLimit parameter to a value higher than 50 then you need to also use the -AcceptLargeDataLoss switch parameter, as shown in the following example: New-MoveRequest -Identity testuser ` -BadItemLimit 100 ` -AcceptLargeDataLoss ` -TargetDatabase DB2 When executing this command, a move request will be created for the testuser mailbox. Up to 100 corrupt items in the source mailbox will be allowed in order to perform a successful move to the new database. You will see a warning in the shell when using these parameters and any corrupt items found in the source mailbox will be skipped when the mailbox is moved.
Read more
  • 0
  • 0
  • 4263

article-image-exchange-server-2010-windows-powershell-troubleshooting-mailboxes
Packt
22 Jul 2011
7 min read
Save for later

Exchange Server 2010 Windows PowerShell: Troubleshooting Mailboxes

Packt
22 Jul 2011
7 min read
Microsoft Exchange 2010 PowerShell Cookbook Manage and maintain your Microsoft Exchange 2010 environment with the Exchange Management Shell and Windows PowerShell 2.0 using this book and eBook The reader will benefit from referring two previous articles: Managing Mailboxes and Reporting on Mailbox. Performing some basic steps To work with the code samples in this article, follow these steps to launch the Exchange Management Shell: Log onto a workstation or server with the Exchange Management Tools installed. Open the Exchange Management Shell by clicking on Start | All Programs | Exchange Server 2010. Click on the Exchange Management Shell shortcut. Checking mailbox logon statistics If you have worked with Exchange 2000 or 2003, you probably remember that you could easily view several mailbox-related details for each mailbox under the Logons node of the Exchange System Manager. These details included the user-name, last access time, and more. When viewing mailboxes in the Exchange Management Console in Exchange 2010, these details are not displayed. In this recipe, we will take a look at how we can gather some of this information the Get-LogonStatistics cmdlet. How to do it... The following command will provide a logon statistics report for all mailboxes in the organization: Get-MailboxServer | Get-LogonStatistics | Select UserName,ApplicationId,ClientVersion,LastAccessTime How it works... The Get-LogonStatistics cmdlet c an be useful for doing some basic checks on client logons, but the information returned from the previous command can be a little confusing and might seem inaccurate. For example, the ClientVersion property returned for each logon will always be reported as the same version number for end-user logons. This is due to the fact that client connections go through the Client Access role in Exchange 2010. Whether or not this will be fixed in future versions is unknown. The ApplicationId property will indicate whether clients are connected via RPC or through Outlook Web App. Keep in mind that, depending on the client, multiple connections could be reported. Client's applications initiate multiple connections, so you will likely notice that this cmdlet will return anywhere from three to five records for each user connected to a mailbox. You will also see connections where the username is reported as the name of one or more databases or a system mailbox. These are generated by transport servers and mailbox assistant agents. There's more... There are a couple of other ways you can run this cmdlet. First, you can generate a report for an individual user. Instead of selecting individual properties, you can pipe the command to Format-List with a wildcard to display all of them: Get-LogonStatistics -Identity testuser | Format-List * You can also retrieve the logon statistics for a particular database using the -Database parameter: Get-LogonStatistics -Database DB1 When users access their mailbox through Outlook Web App you may find that logon statistics for these sessions are missing or not what you would expect when running the Get-LogonStatistics cmdlet. This is because OWA users are not continuously connected to the Exchange server and the OWA client only connects to the server as needed to perform a task. Setting storage quotas for mailboxes One thing that has been around for several versions of Exchange is the concept of storage quotas. Using quotas, we can control the size of each mailbox to ensure that our mailbox databases don't grow out of control. In addition to setting storage quotas at the database level, we can also configure storage quotas on a per-mailbox basis. In this recipe, we will take a look at how to configure mailbox storage quotas from the Exchange Management Shell. How to do it... Use the following command syntax to set custom limits on mailbox: Set-Mailbox -Identity testuser ` -IssueWarningQuota 1gb ` -ProhibitSendQuota 1.5gb ` -ProhibitSendReceiveQuota 2gb ` -UseDatabaseQuotaDefaults $false How it works... The Set-Mailbox cmdlet is used to configure the quota warning and send and receive limits for each mailbox. In this example, we are setting the -IssueWarningQuota parameter to one gigabyte. When the user's mailbox exceeds this size, they will receive a warning message from the system that they are approaching their quota limit. The -ProhibitSendQuota is set to 1.5 gigabytes, and when the total mailbox size exceeds this limit, the user will no longer be able to send messages, although new incoming e-mail messages will still be received. We've set the -ProhibitSendReceiveQuota parameter value to two gigabytes. Once this mailbox reaches this size, the user will no longer be able to send or receive mail. It's important to point out here that we have disabled the option to inherit the storage quota limits from the database by setting the -UseDatabaseQuotaDefaults to $false. If this setting were set to $true, the custom mailbox quota settings would not be used. There's more... By default, mailboxes are configured to inherit their storage quota limits from their parent database. In most cases, this is ideal since you can centrally control the settings for each mailbox in a particular database. However, it is unlikely that having single quota limit for the entire organization will be sufficient. For example, you will probably have a group of managers, VIP users, or executives that require a larger amount of space for their mailboxes. Even though you could create a separate database for these users with higher quota values, this might not make sense in your environment, and instead, you may want to override the database quota defaults with a custom setting on an individual basis. Let's say that all users with their Title set to Manager should have a custom quota setting. We can use the following commands to make this change in bulk: Get-User -RecipientTypeDetails UserMailbox ` -Filter {Title -eq 'Manager'} | Set-Mailbox -IssueWarningQuota 2gb ` -ProhibitSendQuota 2.5gb ` -ProhibitSendReceiveQuota 3gb ` -UseDatabaseQuotaDefaults $false What we are doing here is searching Active Directory with the Get-User cmdlet and filtering the results so that only mailbox-enabled users with their title set to Manager are returned. This command is piped further to get the Set-Mailbox cmdlet which configures the mailbox quota values and disables the option to use the database quota defaults. Finding inactive mailboxes If you support a large Exchange environment, it's likely that users come and go frequently. In this case, it's quite possible over time that you will end up with multiple unused mailboxes. In this recipe, you will learn a couple of techniques used when searching for inactive mailboxes with the Exchange Management Shell. How to do it... The following command will retrieve a list of mailboxes that have not been logged on to in over 90 days: $mailboxes = Get-Mailbox -ResultSize Unlimited $mailboxes | ?{ (Get-MailboxStatistics $_).LastLogonTime -and ` (Get-MailboxStatistics $_).LastLogonTime -le ` (Get-Date).AddDays(-90) } How it works... You can see here that we're retrieving all of the mailboxes in the organization using the Get-Mailbox cmdlet and storing the results in the $mailboxes variable. We then pipe this collection to the Where-Object cmdlet (using the ? alias) and use the Get-MailboxStatistics cmdlet to build a filter. This first part of this filter indicates that we only want to retrieve mailboxes that have a value set for the LastLogonTime property. If this value is $null, it indicates that these mailboxes have never been used, and have probably been recently created, which means that they will probably soon become active mailboxes. The second part of the filter compares the value for the LastLogonTime. If that value is less than or equal to the date 90 days ago then we have a match and the mailbox will be returned. There's more... Finding unused mailboxes in your environment might be as simple as searching for disabled user accounts in Active Directory that are mailbox-enabled. If that is the case, you can use the following one-liner to discover these mailboxes: Get-User -ResultSize Unlimited -RecipientTypeDetails UserMailbox | ?{$_.UserAccountControl -match 'AccountDisabled'} This command uses the Get-User cmdlet to search through all of the mailbox-enabled users in Active Directory. Next, we filter the results even further by piping those results to the Where-Object cmdlet to find any mailboxes where the UserAccountControl property contains the AccountDisabled value, indicating that the associated Active Directory user account has been disabled.
Read more
  • 0
  • 0
  • 9413

article-image-apache-solr-analyzing-your-text-data
Packt
22 Jul 2011
13 min read
Save for later

Apache Solr: Analyzing your Text Data

Packt
22 Jul 2011
13 min read
  Apache Solr 3.1 Cookbook Introduction Type's behavior can be defined in the context of the indexing process or the context of the query process, or both. Furthermore, type definition is composed of tokenizers and filters (both token filters and character filters). Tokenizer specifies how your data will be preprocessed after it is sent to the appropriate field. Analyzer operates on the whole data that is sent to the field. Types can only have one tokenizer. The result of the tokenizer work is a stream of objects called tokens. Next in the analysis chain are the filters. They operate on the tokens in the token stream. And they can do anything with the tokens—changing them, removing them, or for example, making them lowercase. Types can have multiple filters. One additional type of filter is the character filter. The character filters do not operate on tokens from the token stream. They operate on the data that is sent to the field and they are invoked before the data is sent to the analyzer. This article will focus on the data analysis and how to handle the common day-to-day analysis questions and problems. Storing additional information using payloads Imagine that you have a powerful preprocessing tool that can extract information about all the words in the text. Your boss would like you to use it with Solr or at least store the information it returns in Solr. So what can you do? We can use something that is called payload and use it to store that data. This recipe will show you how to do it. How to do it... I assumed that we already have an application that takes care of recognizing the part of speech in our text data. Now we need to add it to the Solr index. To do that we will use payloads, a metadata that can be stored with each occurrence of a term. First of all, you need to modify the index structure. For this, we will add the new field type to the schema.xml file: <fieldtype name="partofspeech" class="solr.TextField"> <analyzer> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="integer" delimiter="|"/> </analyzer> </fieldtype> Now add the field definition part to the schema.xml file: <field name="id" type="string" indexed="true" stored="true" required="true" /> <field name="text" type="text" indexed="true" stored="true" /> <field name="speech" type="partofspeech" indexed="true" stored= "true" multivalued="true" /> Now let's look at what the example data looks like (I named it ch3_payload.xml): <add> <doc> <field name="id">1</field> <field name="text">ugly human</field> <field name="speech">ugly|3 human|6</field> </doc> <doc> <field name="id">2</field> <field name="text">big book example</field> <field name="speech">big|3 book|6 example|1</field> </doc> </add> Let's index our data. To do that, we run the following command from the exampledocs directory (put the ch3_payload.xml file there): java -jarpost.jar ch3_payload.xml How it works... What information can payload hold? It may hold information that is compatible with the encoder type you define for the solr.DelimitedPayloadTokenFilterFactory filter . In our case, we don't need to write our own encoder—we will use the supplied one to store integers. We will use it to store the boost of the term. For example, nouns will be given a token boost value of 6, while the adjectives will be given a boost value of 3. First we have the type definition. We defined a new type in the schema.xml file, named partofspeech based on the Solr text field (attribute class="solr.TextField"). Our tokenizer splits the given text on whitespace characters. Then we have a new filter which handles our payloads. The filter defines an encoder, which in our case is an integer (attribute encoder="integer"). Furthermore, it defines a delimiter which separates the term from the payload. In our case, the separator is the pipe character |. Next we have the field definitions. In our example, we only define three fields: Identifier Text Recognized speech part with payload   Now let's take a look at the example data. We have two simple fields: id and text. The one that we are interested in is the speech field. Look how it is defined. It contains pairs which are made of a term, delimiter, and boost value. For example, book|6. In the example, I decided to boost the nouns with a boost value of 6 and adjectives with the boost value of 3. I also decided that words that cannot be identified by my application, which is used to identify parts of speech, will be given a boost of 1. Pairs are separated with a space character, which in our case will be used to split those pairs. This is the task of the tokenizer which we defined earlier. To index the documents, we use simple post tools provided with the example deployment of Solr. To use it, we invoke the command shown in the example. The post tools will send the data to the default update handler found under the address http://localhost:8983/solr/update. The following parameter is the file that is going to be sent to Solr. You can also post a list of files, not just a single one. That is how you index payloads in Solr. In the 1.4.1 version of Solr, there is no further support for payloads. Hopefully this will change. But for now, you need to write your own query parser and similarity class (or extend the ones present in Solr) to use them. Eliminating XML and HTML tags from the text There are many real-life situations when you have to clean your data. Let's assume that you want to index web pages that your client sends you. You don't know anything about the structure of that page—one thing you know is that you must provide a search mechanism that will enable searching through the content of the pages. Of course, you could index the whole page by splitting it by whitespaces, but then you would probably hear the clients complain about the HTML tags being searchable and so on. So, before we enable searching on the contents of the page, we need to clean the data. In this example, we need to remove the HTML tags. This recipe will show you how to do it with Solr. How to do it... Let's suppose our data looks like this (the ch3_html.xml file): <add> <doc> <field name="id">1</field> <field name="html"><![CDATA[<html><head><title>My page</title></ head><body><p>This is a <b>my</b><i>sample</i> page</body></html> ]]></field> </doc> </add> Now let's take care of the schema.xml file. First add the type definition to the schema.xml file: <fieldType name="html_strip" class="solr.TextField"> <analyzer> <charFilter class="solr.HTMLStripCharFilterFactory"/> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType> And now, add the following to the field definition part of the schema.xml file: <field name="id" type="string" indexed="true" stored="true" required="true" /> <field name="html" type="html_strip" indexed="true" stored="false"/> Let's index our data. To do that, we run the following command from the exampledocs directory (put the ch3_html.xml file there): java -jar post.jar ch3_html.xml If there were no errors, you should see a response like this: SimplePostTool: version 1.2 SimplePostTool: WARNING: Make sure your XML documents are encoded in UTF-8, other encodings are not currently supported SimplePostTool: POSTing files to http://localhost:8983/solr/update.. SimplePostTool: POSTingfile ch3_html.xml SimplePostTool: COMMITting Solr index changes.. How it works... First of all, we have the data example. In the example, we see one file with two fields; the identifier and some HTML data nested in the CDATA section. You must remember to surround the HTML data in CDATA tags if they are full pages, and start from HTML tags like our example, otherwise Solr will have problems with parsing the data. However, if you only have some tags present in the data, you shouldn't worry. Next, we have the html_strip type definition. It is based on solr.TextField to enable full-text searching. Following that, we have a character filter which handles the HTML and the XML tags stripping. This is something new in Solr 1.4. The character filters are invoked before the data is sent to the tokenizer. This way they operate on untokenized data. In our case, the character filter strips the HTML and XML tags, attributes, and so on. Then it sends the data to the tokenizer, which splits the data by whitespace characters. The one and only filter defined in our type makes the tokens lowercase to simplify the search. To index the documents, we use simple post tools provided with the example deployment of Solr. To use it we invoke the command shown in the example. The post tools will send the data to the default update handler found under the address http://localhost:8983/solr/ update. The parameter of the command execution is the file that is going to be sent to Solr. You can also post a list of files, not just a single one. As you can see, the sample response from the post tools is rather informative. It provides information about the update handler address, files that were sent, and information about commits being performed. If you want to check how your data was indexed, remember not to be mistaken when you choose to store the field contents (attribute stored="true"). The stored value is the original one sent to Solr, so you won't be able to see the filters in action. If you wish to check the actual data structures, please take a look at the Luke utility (a utility that lets you see the index structure, field values, and operate on the index). Luke can be found at the following address: http://code.google.com/p/luke Solr provides a tool that lets you see how your data is analyzed. That tool is a part of Solr administration pages. Copying the contents of one field to another Imagine that you have many big XML files that hold information about the books that are stored on library shelves. There is not much data, just the unique identifier, name of the book, and the name of the author. One day your boss comes to you and says: "Hey, we want to facet and sort on the basis of the book author". You can change your XML and add two fields, but why do that when you can use Solr to do that for you? Well, Solr won't modify your data, but it can copy the data from one field to another. This recipe will show you how to do that. How to do it... Let's assume that our data looks like this: <add> <doc> <field name="id">1</field> <field name="name">Solr Cookbook</field> <field name="author">John Kowalsky</field> </doc> <doc> <field name="id">2</field> <field name="name">Some other book</field> <field name="author">Jane Kowalsky</field> </doc> </add> We want the contents of the author field to be present in the fields named author, author_facet, and author sort. So let's define the copy fields in the schema.xml file (place the following right after the fields section): <copyField source="author"dest="author_facet"/> <copyField source="author"dest="author_sort"/> And that's all. Solr will take care of the rest. The field definition part of the schema.xml file could look like this: <field name="id" type="string" indexed="true" stored="true" required="true"/> <field name="author" type="text" indexed="true" stored="true" multiValued="true"/> <field name="name" type="text" indexed="true" stored="true"/> <field name="author_facet" type="string" indexed="true" stored="false"/> <field name="author_sort" type="alphaOnlySort" indexed="true" stored="false"/> Let's index our data. To do that, we run the following command from the exampledocs directory (put the ch3_html.xml file there): java -jar post.jar data.xml How it works... As you can see in the example, we have only three fields defined in our sample data XML file. There are two fields which we are not particularly interested in: id and name. The field that interests us the most is the author field. As I have mentioned earlier, we want to place the contents of that field in three fields: Author (the actual field that will be holding the data) author_ sort author_facet   To do that we use the copy fields. Those instructions are defined in the schema.xml file, right after the field definitions, that is, after the tag. To define a copy field, we need to specify a source field (attribute source) and a destination field (attribute dest). After the definitions, like those in the example, Solr will copy the contents of the source fields to the destination fields during the indexing process. There is one thing that you have to be aware of—the content is copied before the analysis process takes place. This means that the data is copied as it is stored in the source. There's more... There are a few things worth nothing when talking about copying contents of the field to another field. Copying the contents of dynamic fields to one field You can also copy multiple field content to one field. To do that, you should define a copy field like this: <copyField source="*_author"dest="authors"/> The definition like the one above would copy all of the fields that end with _author to one field named authors. Remember that if you copy multiple fields to one field, the destination field should be defined as multivalued. Limiting the number of characters copied There may be situations where you only need to copy a defined number of characters from one field to another. To do that we add the maxChars attribute to the copy field definition. It can look like this: <copyField source="author" dest="author_facet" maxChars="200"/> The above definition tells Solr to copy upto 200 characters from the author field to the author_facet field. This attribute can be very useful when copying the content of multiple fields to one field.
Read more
  • 0
  • 0
  • 5326

article-image-how-storage-works-amazon
Packt
22 Jul 2011
9 min read
Save for later

How Storage Works on Amazon

Packt
22 Jul 2011
9 min read
Amazon Web Services: Migrating your .NET Enterprise Application Evaluate your Cloud requirements and successfully migrate your .NET Enterprise Application to the Amazon Web Services Platform Creating a S3 bucket with logging Logging provides detailed information on who accessed what data in your bucket and when. However, to turn on logging for a bucket, an existing bucket must have already been created to hold the logging information, as this is where AWS stores it. To create a bucket with logging, click on the Create Bucket button in the Buckets sidebar: This time, however, click on the Set Up Logging button . You will be presented with a dialog that allows you to choose the location for the logging information, as well as the prefix for your logging data: You will note that we have pointed the logging information back at the original bucket migrate_to_aws_01 Logging information will not appear immediately; however, a file will be created every few minutes depending on activity. The following screenshot shows an example of the files that are created: Before jumping right into the command-line tools, it should be noted that the AWS Console includes a Java-based multi-file upload utility that allows a maximum size of 300 MB for each file Using the S3 command-line tools Unfortunately, Amazon does not provide official command-line tools for S3 similar to the tools they have provided for EC2. However, there is an excellent simple free utility provided at o http://s3.codeplex.com, called S3.exe, that requires no installation and runs without the requirement of third-party packages. To install the program, just download it from the website and copy it to your C:AWS folder. Setting up your credentials with S3.exe Before we can run S3.exe, we first need to set up our credentials. To do that you will need to get your S3 Access Key and your S3 Secret Access Key from the credentials page of your AWS account. Browse to the following location in your browser, https://aws-portal.amazon.com/gp/aws/developer/account/ index.html?ie=UTF8&action=access-key and scroll down to the Access Credentials section: The Access Key is displayed in this screen; however, to get your Secret Access Key you will need to click on the Show link under the Secret Access Key heading. Run the following command to set up S3.exe: C:AWS>s3 auth AKIAIIJXIP5XC6NW3KTQ 9UpktBlqDroY5C4Q7OnlF1pNXtK332TslYFsWy9R To check that the tool has been installed correctly, run the s3 list command: C:AWS>s3 list You should get the following result: Copying files to S3 using S3.exe First, create a file called myfile.txt in the C:AWS directory. To copy this file to an S3 bucket that you own, use the following command: c:AWS>s3 put migrate_to_aws_02 myfile.txt This command copies the file to the migrate_to_aws_02 bucket with the default permissions of full control for the owner. You will need to refresh the AWS Console to see the file listed. (Move the mouse over the image to enlarge it.) Uploading larger files to AWS can be problematic, as any network connectivity issues during the upload will terminate the upload. To upload larger files, use the following syntax: C:AWS>s3 put migrate_to_aws_02/mybigfile/ mybigfile.txt /big This breaks the upload into small chunks, which can be reversed when getting the file back again. If you run the same command again, you will note that no chunks are uploaded. This is because S3.exe does not upload a chunk again if the checksum matches. Retrieving files from S3 using S3.exe Retrieving files from S3 is the reverse of copying files up to S3. To get a single file back use: C:AWS>s3 get migrate_to_aws_02/myfile.txt To get our big file back again use: C:AWS>s3 get migrate_to_aws_02/mybigfile/mybigfile.txt /big The S3.exe command automatically recombines our large file chunks back into a single file. Importing and exporting large amounts of data in and out of S3 Because S3 lives in the cloud within Amazon's data centers, it may be costly and time consuming to transfer large amounts of data to and from Amazon's data center to your own data center. An example of a large file transfer may be a large database backup file that you may wish to migrate from your own data center to AWS. Luckily for us, Amazon provides the AWS Import/Export Service for the US Standard and EU (Ireland) regions. However, this service is not supported for the other two regions at this time. The AWS Import service allows you to place your data on a portable hard drive and physically mail your hard disk to Amazon for uploading/downloading of your data from within Amazon's data center. Amazon provides the following recommendations for when to use this service. If your connection is 1.55Mbps and your data is 100GB or more If your connection is 10Mbps and your data is 600GB or more If your connection is 44.736Mbps and your data is 2TB or more If your connection is 100Mbps and your data is 5TB or more Make sure if you choose either the US West (California) or Asia Pacific (Singapore) regions that you do not need access to the AWS Import/ Export service, as it is not available in these regions. Setting up the Import/Export service To begin using this service once again, you will need to sign up for this service separately from your other services. Click on the Sign Up for AWS Import/Export button located on the product page http://aws.amazon.com/importexport, confirm the pricing and click on the Complete Sign Up button . Once again, you will need to wait for the service to become active: Current costs are:     Cost Type US East US West EU APAC Device handling $80.00 $80.00 $80.00 $99.00 Data loading time $2.49 per data loading hour $2.49 per data loading hour $2.49 per data loading hour $2.99 per data loading hour Using the Import/Export service To use the Import/Export service, first make sure that your external disk device conforms to Amazon's specifications. Confirming your device specifications The details are specified at http://aws.amazon.com/importexport/#supported_ devices, but essentially as long as it is a standard external USB 2.0 hard drive or a rack mountable device less than 8Us supporting eSATA then you will have no problems. Remember to supply a US power plug adapter if you are not located in the United States. Downloading and installing the command-line service tool Once you have confirmed that your device meets Amazon's specifications, download the command-line tools for the Import/Export service. At this time, it is not possible to use this service from the AWS Console. The tools are located at http:// awsimportexport.s3.amazonaws.com/importexport-webservice-tool.zip. Copy the .zip file to the C:AWS directory and unzip them, they will most likely end up in the following directory, C:AWSimportexport-webservice-tool. Creating a job To create a job, change directory to the C:AWSimportexport-webservice- tool directory, open notepad, and paste the following text into a new file: manifestVersion: 2.0 bucket: migrate_to_aws_01 accessKeyId: AKIAIIJXIP5XC6NW3KTQ deviceId: 12345678 eraseDevice: no returnAddress: name: Rob Linton street1: Level 1, Migrate St city: Amazon City stateOrProvince: Amazon postalCode: 1000 phoneNumber: 12345678 country: Amazonia customs: dataDescription: Test Data encryptedData: yes encryptionClassification: 5D992 exportCertifierName: Rob Linton requiresExportLicense: no deviceValue: 250.00 deviceCountryOfOrigin: China deviceType: externalStorageDevice Edit the text to reflect your own postal address, accessKeyId, bucket name, and save the file as MyManifest.txt. For more information on the customs configuration items refer to http://docs.amazonwebservices. com/AWSImportExport/latest/DG/index.html?ManifestFileRef_ international.html. If you are located outside of the United States a customs section in the manifest is a requirement. In the same folder open the AWSCredentials.properties file in notepad, and copy and paste in both your AWS Access Key ID and your AWS Secret Access Key. The file should look like this: # Fill in your AWS Access Key ID and Secret Access Key # http://aws.amazon.com/security-credentials accessKeyId:AKIAIIJXIP5XC6NW3KTQ secretKey:9UpktBlqDroY5C4Q7OnlF1pNXtK332TslYFsWy9R Now that you have created the required files, run the following command in the same directory. C:AWSimportexport-webservice-tool>java -jar lib/AWSImportExportWebServiceTool-1.0.jar CreateJob Import MyManifest.txt . (Move the mouse over the image to enlarge it.) Your job will be created along with a .SIGNATURE file in the same directory. Copying the data to your disk device Now you are ready to copy your data to your external disk device. However, before you start, it is mandatory to copy the .SIGNATURE file created in the previous step into the root directory of your disk device. Sending your disk device Once your data and the .SIGNATURE file have been copied to your disk device, print out the packing slip and fill out the details. The JOBID can be obtained in the output from your earlier create job request, in our example the JOBID is XHNHC. The DEVICE IDENTIFIER is the device serial number, which was entered into the manifest file, in our example it was 12345678. The packing slip must be enclosed in the package used to send your disk device.   Each package can have only one storage device and one packing slip, multiple storage devices must be sent separately. Address the package with the address output in the create job request: AWS Import/Export JOBID TTVRP 2646 Rainier Ave South Suite 1060 Seattle, WA 98144 Please note that this address may change depending on what region you are sending your data to. The correct address will always be returned from the Create Job command in the AWS Import/Export Tool. Managing your Import/Export jobs Once your job has been submitted, the only way to get the current status of your job or to modify your job is to run the AWS Import/Export command-line tool. Here is an example of how to list your jobs and how to cancel a job. To get a list of your current jobs, you can run the following command: C:AWSimportexport-webservice-tool>java -jar lib/AWSImportExportWebServiceTool-1.0.jar ListJobs To cancel a job, you can run the following command: C:AWSimportexport-webservice-tool>java -jar lib/AWSImportExportWebServiceTool-1.0.jar CancelJob XHNHC (Move the mouse over the image to enlarge it.)
Read more
  • 0
  • 0
  • 6082

article-image-android-30-application-development-gps-locations-and-maps
Packt
22 Jul 2011
7 min read
Save for later

Android 3.0 Application Development: GPS, Locations, and Maps

Packt
22 Jul 2011
7 min read
  Android 3.0 Application Development Cookbook Design and develop rich smartphone and tablet applications for Android 3.0         Introduction For managing location based information, Android provides the android.location package which in turn gives us the LocationManager class that gives us access to location based functions such as the latitude and longitude of a device's position. Tracking a device over time is made equally convenient and the LocationListener class monitors changes in location as they occur. Listening for location changes is only a part of the story, as Google provides APIs for managing Google Maps data and displaying and manipulating maps through the use of the MapView and MapController classes. These powerful tools require us to sign up with Google first, and once done enable us to zoom in and out of maps, pan to any location that we are looking for, and when we want to, include application information on a map, and even add our own layers to maps and mark locations on a Google map. Detecting a device's location Android locations are expressed in terms of latitude and longitude coordinates. The default format is degrees. The Location object can also be used to store a time-stamp and other information such as speed and distance traveled. Although obtaining a device's last known location does not always yield the most accurate information, it is often the first reading that we may want. It is fast, simple to employ, and makes a good introduction to the LocationManager. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> How to do it... Use the TextView provided in the main.xml file and give it a resource ID: android:id="@+id/text_view" Declare a TextView as a class-wide field in the Java activity code: TextView textView; Then, find it in the usual way, from within the onCreate() method: textView = (TextView) findViewById(R.id.text_view); Next, and still within onCreate(), declare and define our LocationManager: LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Then, to retrieve the last known location using GPS and display this in the text view, add these lines: Location loc = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER); textView.setText("latitude: " + loc.getLatitude() + "nlongitude: " + loc.getLongitude()); Run the code on a handset or emulator to obtain its location: How it works... The use of a LocationManager to obtain the device's last known location is very straightforward. As with other system services, we obtained it with getSystemService() and the getLastKnownLocation() method returns the Location object itself, which can be further queried to provide latitude and longitude coordinates. We could have done more with the Location object, for example Location.getAltitude() will return altitude and getDistance(Location) and getBearing(Location) will return distance and bearing to another Location. It is possible to send mock locations to an emulator using the DDMS perspective in Eclipse: Before sending location data this way, make sure that you have set the emulator to allow mock locations under Settings | Applications | Development. It is worth noting that although use of the getLastKnownLocation() method may not always be accurate, particularly if the device has been switched off for some time, it does have the advantage of yielding almost immediate results. There's more... Using GPS to obtain a location has a couple of drawbacks. Firstly, it does not work indoors; and secondly, it is very demanding on the battery. Location can be determined by comparing cell tower signal strengths, and although this method is not as accurate, it works well indoors and is much more considerate to the device's battery. Obtaining a location with a network provider The network provider is set up in exactly the same way as the previous GPS example, simply exchange the Location declaration with: Location loc = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); You will also need to change, or amend, the permission in the manifest file with: <uses-permission android_name="android.permission.ACCESS_COURSE_LOCATION" /> Listening for location changes Obtaining the last known location as we did in the previous recipe is all well and good and handy for retrieving a Location quickly, but it can be unreliable if the handset has been switched off or if the user is on the move. Ideally we want to be able to detect location changes as they happen and to do this we employ a LocationListener. In this recipe we will create a simple application that keeps track of a mobile device's movements. Getting ready This task can be performed most easily by starting where the previous one left off. If you have not completed that task yet, do so now—it is very short—then return here. If you have already completed the recipe then simply open it up to proceed. How to do it... First, move the declaration of our LocationManager so that it is a class-wide field: LocationManager manager; In the main Java activity code, before the TextView.setText() call, add the following three lines: LocationListener listener = new MyLocationListener(); manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 50, listener); Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER); Now create an inner class called MyLocationListener that implements LocationListener: LocationListener: public class MyLocationListener implements LocationListener { } Eclipse will most likely insist that you add some unimplemented methods and you should do so. For now, only complete one of them, the onLocationChanged() callback: @Override public void onLocationChanged(Location l) { textView.setText("/n/nlatitude: " + l.getLatitude() + "nlongitude: " + l.getLongitude()); } Leave the others as they are: @Override public void onProviderDisabled(String provider) {} @Override public void onProviderEnabled(String provider) {} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} If you want to test this code on an emulator, then go right ahead. However, this code will create a serious drain on the battery of a handset, and it is wise to switch our listener off when it is not needed. Here we have used the activity's onPause() and onResume() functions to control this. You may wish to include these statements in any part of your activity's life cycle that suits your application's purpose: @Override protected void onResume() { super.onResume(); manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 50, listener); } @Override protected void onPause() { super.onPause(); manager.removeUpdates(this); } If you have not already tested this application, do so now. You will need to move around if you are testing it on a real device, or send mock locations to an emulator to see the code in action: How it works... In this recipe we used the LocationManager to provide location updates roughly every 30 seconds (30000 milliseconds) or whenever the location changed by more than 50 meters. We say 'roughly' because these values work only as a guide and the actual frequency of updates often varies from the values we set. Nevertheless, setting these two parameters of the requestLocationUpdates() method to high values can make a big difference to the amount of battery power the GPS provider consumes. Hopefully the use of the provider and the LocationListener as the other two parameters is self explanatory. The LocationListener operates very much as other listeners do and the purpose of the onProviderEnabled() and onProviderDisabled() should be clear. The onStatusChanged() method is called whenever a provider becomes unavailable after a period of availability or vice versa. The int, status can represent 0 = OUT_OF_SERVICE, 1 = TEMPORARILY_UNAVAILABLE, or 2 = AVAILABLE.  
Read more
  • 0
  • 0
  • 4961

article-image-exchange-server-2010-windows-powershell-managing-mailboxes
Packt
22 Jul 2011
8 min read
Save for later

Exchange Server 2010 Windows PowerShell: Managing Mailboxes

Packt
22 Jul 2011
8 min read
  Microsoft Exchange 2010 PowerShell Cookbook Manage and maintain your Microsoft Exchange 2010 environment with the Exchange Management Shell and Windows PowerShell 2.0 using this book and eBook The reader will benefit from referring two previous articles: Troubleshooting Mailboxes and Reporting on Mailbox Performing some basic steps To work with the code samples in this article, follow these steps to launch the Exchange Management Shell: Log onto a workstation or server with the Exchange Management Tools installed. Open the Exchange Management Shell by clicking on Start | All Programs | Exchange Server 2010. Click on the Exchange Management Shell shortcut. Importing and exporting mailboxes If you have worked with Exchange for a long time, you have probably used utilities such as ExMerge or the Exchange 2007 Management Shell to import and export data between mailboxes and PST files. While these tools were useful for their time, they had some limitations. For example, ExMerge was the main import and export utility starting with Exchange 5.5 and continuing on to Exchange 2003, but it was difficult to automate. Exchange 2007 included the Import-Mailbox and Export-Mailbox cmdlets th at made it easier to automate these tasks through PowerShell scripts. Unfortunately, the Export-Mailbox cmdlet required both a 32-bit workstation running the 32-bit version of the Exchange 2007 Management tools and Microsoft Outlook 2003 SP2 or later. With the release of Exchange 2010 SP1, we have a new set of cmdlets that can be used to manage the import and export operations for Exchange mailboxes. These new cmdlets have no dependencies on a management workstation and there is no requirement to install Outlook to perform these tasks. The Mailbox Replication Service (MRS) that runs on the Client Access Server (CAS) role introduces a new concept called mailbox import and export requests that implements this functionality as a server-side process. In this recipe, you will learn how to configure your environment and use these cmdlets to automate mailbox import and export requests. How to do it... Let's start off by exporting a mailbox to a PST ? le. First, you need to add an RBAC role assignment for your account. Assign the Mailbox Import Export role to your account using the following command. You will need to restart the shell after running this command in order for the assigned cmdlets to be visible: New-ManagementRoleAssignment -Role "Mailbox Import Export" ` -User administrator Next, you will need to create a network share that can be used to store the PST file. When you create the share, make sure that the Exchange Trusted Subsystem group in Active Directory has at least read/write NTFS permissions on the folder, and also has at least modify share permissions. The last step is to use the New-MailboxExportRequest cmdlet to export the data for a mailbox, using the following syntax: New-MailboxExportRequest -Mailbox testuser ` -Filepath contoso-ex01exporttestuser.pst How it works... By default, the built-in Mailbox Import Export role is not assigned to anyone, including the administrators. This means that, out of the box, you will not be able to run the *-MailboxExportRequest cmdlets, even if you are a member of the Organization Management role group. Therefore, the ? rst step in the process is to assign your account to this role using the New-ManagementRoleAssignment cmdlet. I n the previous example, you can see that we created a direct assignment to the administrator's user account. This can be your administrative account, or an actual role group that you are already a member of. If needed, you can specify that the role be assigned to a role group or an Active Directory security group using the -SecurityGroup parameter. The location used for imported and exported PSTs must be a valid UNC path that the Exchange Trusted Subsystem group has access to. This is because the cmdlets that you execute are actually running under the security context of the Exchange servers in this group group. This is required to implement the new RBAC security model, and, therefore, the Share and NTFS permissions must be assigned to this group and not your user account specifically. The syntax for the import and export commands is fairly straightforward. Looking at the command used in the previous example, you can see that we were able to easily create an export request for a specified mailbox using a specific file share on the network. Using additional parameters, we can do other interesting things, such as only exporting specific folders of a mailbox to a PST: New-MailboxExportRequest -Mailbox testuser ` -IncludeFolders "Sent Items" ` -FilePath contoso-ex01exporttestuser_sent.pst ` -ExcludeDumpster As you can see from the command, we are only exporting the Sent Items folder from the testuser mailbox and we are excluding the items in the dumpster. Here is another example that exports data from an archive mailbox: New-MailboxExportRequest -Mailbox testuser ` -ContentFilter {Received -lt "09/01/2010"} ` -FilePath contoso-ex01exporttestuser_archive.pst ` -ExcludeDumpster ` -IsArchive Here we are specifying that we want to only export data from the archive mailbox by using the -IsArchive switch parameter . In addition, we are limiting the amount of data exported from the mailbox using the -ContentFilter parameter . We are only including items that were received before 09/01/2010. In addition to the Received property, the -ContentFilter parameter allows you to highly customize the data that is exported. You can create upto 10 mailbox export requests per mailbox without manually specifying a name for the export request. Once you have reached this limit, you either need to specify a unique name for the export request, or delete some of the previous export requests using the Remove-MailboxExportRequest cmdlet. Using the -ContentFilter parameter, you can filter the recipient, types of attachments that were included in a message, text in the body, and more. For a complete list of available property names, check out the Filterable Properties for the -ContentFilter Parameter on TechNet at the following URL: http://technet.microsoft.com/en-us/library/ff601762.aspx There's more... You can use the Get-MailboxImportRequest and Get-MailboxExportRequest cmdlets to view the status of your import and export tasks. To view all requests, simply run the appropriate Get-* cmdlet . If you want to narrow your search, you can use the -Mailbox and -Status parameters: Get-MailboxExportRequest -Mailbox testuser -Status Failed This command will return all of the export requests made for the testuser mailbox that have a failed status. You can use the same syntax with the import version of this cmdlet to review similar information.   When it comes to advanced reporting of import or export requests, there are two cmdlets available that you can use. Get-MailboxExportRequestStatistics and Get-MailboxImportRequestStatistics can be used to provide detailed information about the tasks associated with a particular operation. For example, take a look at the following script: foreach($i in Get-MailboxExportRequest) { Get-MailboxExportRequestStatistics $i | select-object SourceAlias,Status,PercentComplete } This will provide a brief report for each export request. This can be useful when you are performing multiple import or export operations and need to check the status of each one. Importing data into mailboxes The New-MailboxImportRequest cmdlet works similarly to the New-MailboxExportRequest cmdlet. Most of the parameters shown in the previous examples are available with both cmdlets. For example, we can import data into a specific folder in an inbox with the following command: New-MailboxImportRequest -Mailbox sysadmin ` -IncludeFolders "Sent Items" ` -FilePath contoso-ex01exporttestuser_sent.pst This command imports the testuser PST into the Sent Items folder of the sysadmin mailbox. In addition to exporting data from archive mailboxes, we can also import data into archive mailboxes with the -IsArchive switch parameter. Taking it a step further Let's create a script that will export all of the mailboxes in your organization to individual PST files stored in a central location. Create a new file called Export.ps1 and save it in the C: drive. Using a text editor, open the file and add the following code, and then save the file: param($Path, $BatchName) foreach($i in Get-Mailbox -ResultSize Unlimited) { $filepath = Join-Path -Path $Path -ChildPath "$($_.alias).pst" New-MailboxExportRequest -Mailbox $i ` -FilePath $filepath ` -BatchName $BatchName } This script provides a couple of parameters used to control the behavior of the mailbox export requests. First, the -Path parameter will allow us to specify a UNC share for our exported mailboxes. Secondly, the -BatchName parameter is used to logically group the export requests using a friendly common name. As we loop through each mailbox, we are doing a few things. We are using the value of the -Path parameter as the root directory for the PST file, and we are using the alias of the mailbox for the base filename. This will ensure that each PST file is stored centrally in the required location using a unique filename that matches the mailbox alias. To execute the preceding script, the command might look something like this: $batch = "Export for (Get-Date).ToShortDateString()" .Export.ps1 -Path contosoex01export -BatchName$batch This will create each mailbox export request using a batch name such as Export for 10/26/2010. Then you can easily check the status of all the mailbox export requests that are grouped into that batch name using the following command: Get-MailboxExportRequestStatistics | ?{$_.BatchName -eq "Export for 10/26/2010"} | select SourceAlias,Status,PercentComplete This one-liner will give you a brief report on each of the export requests performed in the batch created on 10/26/2010 that can be reviewed in the shell, exported to a text or CSV file, or e-mailed to another user.
Read more
  • 0
  • 0
  • 6052
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-rhomobile-faqs
Packt
21 Jul 2011
3 min read
Save for later

Rhomobile FAQs

Packt
21 Jul 2011
3 min read
  Rhomobile Beginner's Guide Step-by-step instructions to build an enterprise mobile web application from scratch         Read more about this book       (For more resources on this topic, see here.) Q: Does Rhomobile create a pure Native Application? A: Yes. Rhomobile creates a pure Native Application. This Application is similar to an Application available in i-store. This application can use device capabilities such as GPS, PIM contacts and calendar, camera, native mapping, push, barcode, signature capture, and Bluetooth. These are much faster than Browser-based applications.   Q: I am new to Ruby should I use Rhomobile? A: Although you need to know Ruby to write Rhodes applications, we realize that many folks learn both Ruby and Rhomobile at the same time. As Rhomobile products require an elementary level of Ruby knowledge, this will not affect your learning curve. But I recommend that you go to any Ruby tutorial online.   Q: Is Rhomobile Free? A: Rhodes is free and open source under MIT Licence. To use RhoSync, you must purchase a commercial license when development commences or you must open source your app under the GPL license. The pricing and details can be found at www.rhomobile.com.   Q: Is support available for Rhomobile? A: Yes. However, you have to purchase a Rhodes Enterprise License and the Rhodes Commercial License to get commercial support. Apart from the Rhomobile support, there are various webinars and tutorials available on www.rhomobile.com. Another good support resource is the Rhomobile Google group, where Rhomobile experts are there to help you.   Q: What about Rhomobile security? A: Both Rhodes and RhoSync support use of https as a transport. In fact it is easier with Rhodes than with native code. You just list the https URL and Rhodes will connect to the backend appropriately. This is simple in contrast to underlying SDKs where significantly different code is written to connect to an https URL.   Q: Does Rhomobile support HTML5? A: Yes, Rhomobile supports HTML5 tags provided the device you are targeting also supports them.   Q: Can we write unit test case for the code? A: Yes, we can write unit test case in Rhodes.   Q: Can we use Ruby gems with Rhodes? A: Yes, we can use Ruby gems with Rhodes. We have to include them in the Rhodes configuration file.   Q: Do we need to have knowledge of different device databases? A: No, we don't need to have prior knowledge of those databases, Rhodes will take care of this. We write our query using Object-relational mapping (ORM) called Rhom and it is the work of ORM to shape the query.   Summary In this article we saw some of the most frequently asked questions on Rhomobile. Further resources on this subject: An Introduction to Rhomobile [Article] Getting Started with Internet Explorer Mobile [Article] jQuery Mobile: Organizing Information with List Views [Article] jQuery Mobile: Collapsible Blocks and Theming Content [Article] Fundamentals of XHTML MP in Mobile Web Development [Article]
Read more
  • 0
  • 0
  • 2570

article-image-alfresco-3-web-scripts
Packt
21 Jul 2011
6 min read
Save for later

Alfresco 3: Web Scripts

Packt
21 Jul 2011
6 min read
  Alfresco 3 Cookbook Over 70 recipes for implementing the most important functionalities of Alfresco Introduction You all know about Web Services – which took the web development world by storm a few years ago. Web Services have been instrumental in constructing Web APIs (Application Programming Interface) and making the web applications work as Service-Oriented Architecture. In the new Web 2.0 world, however, many criticisms arose around traditional Web Services – thus RESTful services came into the picture. REST (Representational State Transfer) attempts to expose the APIs using HTTP or similar protocol and interfaces using well-known, light-weight and standard methods such as GET, POST, PUT, DELETE, and so on. Alfresco Web Scripts provide RESTful APIs of the repository services and functions. Traditionally, ECM systems have been exposing the interfaces using RPC (Remote Procedure Call) – but gradually it turned out that RPC-based APIs are not particularly suitable in the wide Internet arena where multiple environments and technologies reside together and talk seamlessly. In the case of Web Scripts, the RESTful services overcome all these problems and integration with an ECM repository has never been so easy and secure. Alfresco Web Scripts were introduced in 2006 and since then it has been quite popular with the developer and system integrator community for implementing services on top of the Alfresco repository and to amalgamate Alfresco with any other system. What is a Web Script? A Web Script is simply a URI bound to a service using standard HTTP methods such as GET, POST, PUT, or DELETE. Web Scripts can be written using simply the Alfresco JavaScript APIs and Freemarker templates, and optionally Java API as well with or without any Freemarker template. For example, the http://localhost:8080/alfresco/service/api/search/person.html ?q=admin&p=1&c=10 URL will invoke the search service and return the output in HTML. Internally, a script has been written using JavaScript API (or Java API) that performs the search and a FreeMarker template is written to render the search output in a structured HTML format. All the Web Scripts are exposed as services and are generally prefixed with http://<<server-url>>/<<context-path>>/<<servicepath>>. In a standard scenario, this is http://localhost:8080/alfresco/service Web Script architecture Alfresco Web Scripts strictly follow the MVC architecture. Controller: Written using Alfresco Java or JavaScript API, you implement your business requirements for the Web Script in this layer. You also prepare your data model that is returned to the view layer. The controller code interacts with the repository via the APIs and other services and processes the business implementations. View: Written using Freemarker templates, you implement exactly what you want to return in your Web Script. For data Web Scripts you construct your JSON or XML data using the template; and for presentation Web Scripts you build your output HTML. The view can be implemented using Freemarker templates, or using Java-backed Web Script classes. Model: Normally constructed in the controller layer (in Java or JavaScript), these values are automatically available in the view layer. Types of Web Scripts Depending on the purpose and output, Web Scripts can be categorized in two types: Data Web Scripts: These Web Scripts mostly return data in plenty after processing of business requirements. Such Web Scripts are mostly used to retrieve, update, and create content in the repository or query the repository. Presentation Web Scripts: When you want to build a user interface using Web Scripts, you use these Web Scripts. They mostly return HTML output. Such Web Scripts are mostly used for creating dashlets in Alfresco Explorer or Alfresco Share or for creating JSR-168 portlets. Note that this categorization of Web Script is not technically different—it is just a logical separation. This means data Web Scripts and presentation Web Scripts are not technically dissimilar, only usage and purpose is different. Web Script files Defining and creating a Web Script in Alfresco requires creating certain files in particular folders. These files are: Web Script Descriptor: The descriptor is an XML file used to define the Web Script – the name of the script, the URL(s) on which the script can be invoked, the authentication mechanism of the script and so on. The name of the descriptor file should be of the form: <<service-id>>.<<http-method>>. desc.xml; for example, helloworld.get.desc.xml. Freemarker Template Response file(s) optional: The Freemarker Template output file(s) is the FTL file which is returned as the result of the Web Script. The name of the template files should be of the form: &lt;<service-id>>.<<httpmethod>>.<< response-format>>.ftl; for example, helloworld.get.html.ftl and helloworld.get.json.ftl. Controller JavaScript file (optional): The Controller JavaScript file is the business layer of your Web Script. The name of the JavaScript file should be of the form: <<service-id>>.<<http-method>>.js; for example, helloworld.get.js. Controller Java file (optional): You can write your business implementations in Java classes as well, instead of using JavaScript API. Configuration file (optional): You can optionally include a configuration XML file. The name of the file should be of the form: <<service-id>>.<<http-method>>.config.xml; for example, helloworld.get.config.js. Resource Bundle file (optional): These are standard message bundle files that can be used for making Web Script responses localized. The name of message files would be of the form: <<service-id>>.<<http-method>>.properties; for example, helloworld.get.properties. The naming conventions of Web Script files are fixed – they follow particular semantics. Alfresco, by default, has provided a quite rich list of built-in Web Scripts which can be found in the tomcatwebappsalfrescoWEB-INFclassesalfrescotemplateswebscriptsorgalfresco folder. There are a few locations where you can store your Web Scripts. Classpath folder: tomcatwebappsalfrescoWEB-INFclassesalfrescotemplateswebscripts Classpath folder (extension): tomcatwebappsalfrescoWEB-INFclassesalfrescoextensiontemplateswebscripts Repository folder: /Company Home/Data Dictionary/Web Scripts Repository folder (extension): /Company Home/Data Dictionary/Web Scripts Extensions It is not advised to keep your Web Scripts in the orgalfresco folder; this folder is reserved for Alfresco default Web Scripts. Create your own folders instead. Or better, you should create your Web Scripts in the extension folders. Web Script parameters You of course need to pass some parameters to your Web Script and execute your business implementations around that. You can pass parameters by query string for the GET Web Scripts. For example: http://localhost:8080/alfresco/service/api/search/person.html?q=admin&p=1&c=10 In this script, we have passed three parameters – q (for the search query), p (for the page index), and c (for the number of items per page). You can also pass parameters bound in HTML form data in the case of POST Web Scripts. One example of such Web Script is to upload a file using Web Script.  
Read more
  • 0
  • 0
  • 2816

article-image-microsoft-sql-server-2008-r2-hierarchies-collections-and-mds-metadata
Packt
21 Jul 2011
9 min read
Save for later

Microsoft SQL Server 2008 R2: Hierarchies, Collections, and MDS Metadata

Packt
21 Jul 2011
9 min read
  Microsoft SQL Server 2008 R2 Master Data Services Manage and maintain your organization's master data effectively with Microsoft SQL Server 2008 R2 Master Data Services         Read more about this book       (For more resources on this subject, see here.) The reader is advised to refer the previous article on Creating and Using Models since this article is related to it. Master Data Services includes a Hierarchy Management feature, where we can: Browse all levels of a hierarchy Move members within a hierarchy Access the Explorer grid and all its functionality for all members of a given hierarchy. As we've seen already, there are two types of hierarchies in MDS—Derived Hierarchies and Explicit Hierarchies. We will look at how to create and use both types of hierarchies now. Derived Hierarchies In our example scenario, as we have stores in many different cities and states, we have a requirement to create a "Stores by Geography" hierarchy. In order to create the hierarchy, carry out the following steps: Navigate to the System Administration function, which can be accessed using the Master Data Manager home page. Hover over the Manage menu and click on the Derived Hierarchies menu item, which will open the Derived Hierarchy Maintenance page. Click on the green plus icon to add a Derived Hierarchy, which will open the Add Derived Hierarchy page. Enter Stores By Geography as the Derived Hierarchy Name and click on save. The Edit Derived Hierarchy page will now be displayed, where we can build the hierarchy. On the left-hand side of the screen we can pick entities to be in our hierarchy, whereas the middle pane of the screen displays the hierarchy in its current state. A preview of the hierarchy with real data is also available on the right-hand side. Drag the Store entity from the left-hand side of the screen and drop it onto the red Current Levels : Stores By Geography node in the center of the screen: The choice of entities of on the left hand side will now change to the only two entities that are related to Store, namely City and StoreType. Repeat the drag-and-drop process, but this time drag the City entity onto the red Current Levels node so that the Current Levels hierarchy is as follows: The Available Entities and Hierarchies pane will now be updated to show the State entity, as this is the only entity related to the City entity. Drag the State entity over to the red Current levels node, above the City entity. The Available Entities and Hierarchies pane will now be updated to show the Country. Drag the Country entity over to the red Current Levels node, above the State entity. This is the last step in building our Stores By Geography hierarchy, which will now be complete. We will now look at how we can browse and edit our new hierarchy. Exploring Derived Hierarchies Before we make any changes to the Derived Hierarchy, we will explore the user interface, so that we are comfortable with how it is used. Carry out the following in order to browse the new hierarchy features: Navigate to the home page and select the Explorer function. Within the Explorer function, hover over the Hierarchies menu, where a menu item called Derived: Stores By Geography should appear. Click on this new item, which will display the Derived Hierarchy, as shown below: The buttons above the hierarchy tree structure are as follows (from left to right): Pin Selected Item—Hides all members apart from the select item and all of its descendants. This option can be useful when browsing large hierarchies. Locate Parent of Selected Item—The immediate parent of the selected member could be hidden, if someone has chosen to pin the item (as above). Locate Parent of Selected Item will locate and display the members parent, as well as any other children of the parent. Refresh Hierarchy—Refreshes the hierarchy tree to display the latest version, as edits could occur outside the immediate tree structure. Show/Hide Names—Toggles the hierarchy view to be either the member code and the name, or just the code. The default is to show the member name and code. Show/Hide Attributes—On the right-hand side of the screen (not shown) the children of the selected item are shown in the Explorer grid, along with all their attributes. This button shows or hides the Explorer grid. View Metadata—Displays a pop-up window that will display the metadata for the selected member. We will discuss metadata towards the end of this article. Select the DE {Germany} member by clicking on it. Note: the checkboxes are not how members are selected; instead, clicking on the member name will select the member. Use the Pin Selected Item button to pin the DE {Germany} member, which will hide the siblings of Germany as shown below: To now locate the parent of DE {Germany}, and display the parent's other children (for example, USA and United Kingdom), click on DE {Germany}, then click on the Locate Parent of Selected Item button. The hierarchy tree will revert back to the original structure that we encountered. Now that we have returned to the original hierarchy structure, expand the US member until the member CA {California} is visible. Click on this member, which will display some of the cities, which we have loaded for the State of California: Editing multiple entitiesThe above point illustrates one of the useful features of the hierarchy editor. Although we can edit the individual entities using their respective Explorer grids, with a Derived Hierarchy, we can edit multiple entities on a single page. We don't actually need to edit the cities for the moment, but we do want to look at showing and hiding the Explorer grid. Click on the Show/Hide Attributes button to hide the Explorer grid. Click on the button again to make the Explorer grid reappear. Finally, we're able to look at the Metadata for the Derived Hierarchy. Click on the View Metadata button to open the Metadata Explorer, which is shown below. This is where we would look for any auxiliary information about the Derived Hierarchy, such as a description to explain what is in the hierarchy. We'll look at metadata in detail at the end of this article. We will now look at how we add a new member in a Derived Hierarchy. Adding a member in a Derived Hierarchy Adding a member in a Derived Hierarchy achieves exactly the same thing as adding a member in the entity itself. The difference is that the member addition process when carried out in a Derived Hierarchy is slightly simplified, as the domain attribute (for example, City in the case of the Store entity) gets automatically completed by MDS. This because in a Derived Hierarchy we choose to add a Store in a particular City, which negates the need to specify the City itself. In our example scenario, we wish to open a new Store in Denver. Carry out the following steps to add the new Store: Expand the US {United States} member of the Stores By Geography hierarchy, and then expand the CO {Colorado} member. Click on the 136 {Denver} member. On the far right-hand side of the screen, the Stores for Denver (of which there are none) will be shown. Click on the green plus icon to begin the process of adding a Store. Enter the Name as AW Denver and enter the Code as 052. Click on the save icon to create the member. Click on the pencil icon to edit the attributes of the new member. Note that the City attribute is already completed for us. Complete the remaining attributes with test data of your choice. Click on the save icon to save the attribute values. Click on the green back arrow button at the top of the screen in order to return to the Derived Hierarchy. Notice that we now have a new Store that exists in the Derived Hierarchy, as well as a new row in the Explorer grid on the right-hand side of the screen. We will now continue to explore the functionality in the hierarchy interface by using Explicit Hierarchies. Explicit Hierarchies Whereas Derived Hierarchies rely on the relationships between different entities in order to exist, all the members within Explicit Hierarchies come from a single entity. The hierarchy is made by making explicit relationships between leaf members and the consolidated members that are used to give the hierarchy more than one level. Explicit Hierarchies are useful in order to represent a ragged hierarchy, which is a hierarchy where the leaf members exist at different levels across the hierarchy. In our example scenario, we wish to create a hierarchy that shows the reporting structures for our stores. Most stores report to a regional center, with the regional centers reporting to Head Office. However, some stores that are deemed to be important report directly to Head Office, which is why we need the Explicit Hierarchy. Creating an Explicit Hierarchy As we saw when creating the original Store entity in the previous article, an Explicit Hierarchy can get automatically created for us when we create an Entity. While that is always an option, right now we will cover how to do this manually. In order to create the Explicit Hierarchy, carry out the following steps: Navigate to the System Administration function. Hover over the Manage menu and click on the Entities menu item. Select the Store entity and then click on the pencil icon to edit the entity. Select Yes from Enable explicit hierarchies and collections drop-down. Enter Store Reporting as the Explicit hierarchy name. Uncheck the checkbox called Include all leaf members in mandatory hierarchy. If the checkbox is unchecked, a special hierarchy node called Unused will be created, where leaf members that are not required in the hierarchy will reside. If the checkbox is checked, then all leaf members will be included in the Explicit Hierarchy. This is shown next: Click on the save icon to make the changes to the entity, which will return us to the Entity Maintenance screen, and conclude the creation of the hierarchy.
Read more
  • 0
  • 0
  • 4263

article-image-microsoft-sql-server-2008-r2-mds-creating-and-using-models
Packt
21 Jul 2011
7 min read
Save for later

Microsoft SQL Server 2008 R2 MDS: Creating and Using Models

Packt
21 Jul 2011
7 min read
Microsoft SQL Server 2008 R2 Master Data Services Manage and maintain your organization's master data effectively with Microsoft SQL Server 2008 R2 Master Data Services MDS object model overview The full MDS object model contains objects such as entities, attributes, members, collections, as well as a number of other objects. The full MDS object model can be summarized by the following diagram: As indicated in the diagram, the Model object is the highest level object in the MDS object model. It represents an MDM subject area, such as Product or Customer. Therefore, it would be normal to have a model called Product, which would contain several different Entities, such as Color, Brand, Style, and an entity called Product itself. Entities have one or more Attributes and instances of entities are known as Members. Instead of an entity just containing attributes, it is possible within MDS to categorize the attributes into groups, which are known as Attribute Groups. There are two types of hierarchies within MDS, namely Derived Hierarchies and Explicit Hierarchies. Derived hierarchies are hierarchies that are created based upon the relationships that exist between entities. For example, the Customer entity may have an attribute called City that is based upon the City entity. In turn, the City entity itself may have a State attribute that is based upon the State entity. The State entity would then have a Country attribute, and so on. This is shown below: Using the relationships between the entities, a Derived Hierarchy called Customer Geography, for example, can be created that would break customers down by their geographic locations. A visual representation of this hierarchy is as follows: A Derived Hierarchy relies on separate entities that share relationships between one another. This is in contrast to an Explicit Hierarchy, whose hierarchy members must all come from a single entity. The point to note though is that the members in an Explicit Hierarchy can be both Leaf Members and also Consolidated Members. The idea behind Explicit Hierarchies is that they can represent ragged data structures whereby the members cannot be easily categorized as being a member of any one given entity. For example, Profit and Loss accounts can exist at different levels. Both the accounts "Cash in Transit" and "Net Profit" are valid accounts, but one is lowlevel and one is a high-level account, plus there are many more accounts that sit in between the two. One solution is to create "Net Profit" as a consolidated member and "Cash In Transit" as a leaf member, all within the same entity. This way, a full ragged Chart of Accounts structure may be created within MDS. Models The first step to get started with Master Data Services is to create a model, as the model is the overall container object for all other objects. We are going to start by creating a practice model called Store—meaning that it will be our single source of retail stores in our fictitious company. Models are created in the Master Data Manager application, within the System Administration functional area. Carry out the following steps to create our Store model: Ensure that the Master Data Manager application is open. To do this, type the URL into your web browser, which will typically be http://servername/MDS/. Click on the System Administration option in the home page, which will take you to the following screen: The tree view that is shown breaks down each of the models that are installed in the MDS environment, showing entities, attributes and other objects within the system. The tree view provides an alternate way to edit some of the MDS objects. Rather than using the tree view, we are going to create a model via the menu at the top of the screen. Hover over the Manage menu and choose the Models menu item. The resulting screen will show a list of the current models within MDS, with the ability to add or edit a model. Click on the familiar Master Data Manager green plus icon in order to add our new model, which will produce the following screen: Enter Store as the Model name. Next there are some settings to configure for the model, via three checkboxes. The settings are: Create entity with same name as model—This is essentially a shortcut to save creating an entity manually after creating the model. We want an entity called Store to be created, so leave this option checked. Create explicit hierarchy with same name as model—Another shortcut, this time to create an Explicit Hierarchy. We will manually create an Explicit Hierarchy later on, so uncheck this box. Include all leaf members in mandatory hierarchy—This setting only applies if we are creating an Explicit Hierarchy. If checked, it will ensure that all leaf members must exist within an Explicit Hierarchy. By unchecking the previous option, this option will be unchecked. Click the "Disk" icon to save and create the new model. Entities and attributes After creating the new model, we are now in a position to create all the entities and attributes that we need to manage our store data. However, before doing this, we need to plan what entities and attributes are needed. This can be summarized by the following table: Attributes Attributes are the building blocks of entities in MDS, and there are three different types, which we need to cover before we can start creating and altering entities. The different types are explained in the following table: Domain attributes and relationships between entities As we left the Create entity with same name as model option checked when creating the model, we will have an entity already created called Store. The task now is to edit the Store entity, in order to set up the attributes that we have defined previously. However, before we can complete the Store entity, we actually need to create several of the other entities. This is because we want some of the Store's attributes to be based on other entities, which is exactly why we need domain attributes. Domain attributes are the method that allow us to create relationships between entities, which we need, for example, in order to create Derived Hierarchies. In addition, they also allow for some good data entity validation as, for example, it would not be possible for a user to enter a new attribute value of "New York" in the City attribute if the member "New York" did not exist in the City entity. If we look at our table of entities and attributes again, there is a column to indicate where we need a domain attribute. If we were building an entity relationship diagram, we would say that a Store has a City and that a City belongs to a State. Creating an entity To focus on the Store entity first, before we can say that its structure is complete, we firstly need to create any entities that the Store entity wants to use as domain attributes. We can clearly see from the previous table that these are City and StoreType. The Country and State entities are also required as domain attributes by other entities. Therefore, carry out the following steps in order to create the remaining entities: Ensure that you are in the System Administration function. Hover over the Manage menu and click on the Entities menu item. Ensure that the Store model is selected from the Model drop-down. Click the green "plus" icon. This will open the Add Entity screen. Enter the following information on the Add Entity screen, as shown below: Enter City as the Entity Name. Choose No to not Enable explicit hierarchies and collections. Click the save icon to create the entity and return to the Entity Maintenance screen. Repeat this process to create the StoreType, Country, and State entities. Once you have finished the Entity Maintenance screen should look as follows:
Read more
  • 0
  • 0
  • 4262
article-image-play-framework-data-validation-using-controllers
Packt
21 Jul 2011
15 min read
Save for later

Play Framework: Data Validation Using Controllers

Packt
21 Jul 2011
15 min read
Play Framework Cookbook Over 60 incredibly effective recipes to take you under the hood and leverage advanced concepts of the Play framework Introduction This article will help you to keep your controllers as clean as possible, with a well defined boundary to your model classes. Always remember that controllers are really only a thin layer to ensure that your data from the outside world is valid before handing it over to your models, or something needs to be specifically adapted to HTTP. URL routing using annotation-based configuration If you do not like the routes file, you can also describe your routes programmatically by adding annotations to your controllers. This has the advantage of not having any additional config file, but also poses the problem of your URLs being dispersed in your code. You can find the source code of this example in the examples/chapter2/annotationcontroller directory. How to do it... Go to your project and install the router module via conf/dependencies.yml: require: - play - play -> router head Then run playdeps and the router module should be installed in the modules/ directory of your application. Change your controller like this: @StaticRoutes({ @ServeStatic(value="/public/", directory="public") }) public class Application extends Controller { @Any(value="/", priority=100) public static void index() { forbidden("Reserved for administrator"); } @Put(value="/", priority=2, accept="application/json") public static void hiddenIndex() { renderText("Secret news here"); } @Post("/ticket") public static void getTicket(String username, String password) { String uuid = UUID.randomUUID().toString(); renderJSON(uuid); } } How it works... Installing and enabling the module should not leave any open questions for you at this point. As you can see in the controller, it is now filled with annotations that resemble the entries in the routes.conf file, which you could possibly have deleted by now for this example. However, then your application will not start, so you have to have an empty file at least. The @ServeStatic annotation replaces the static command in the routes file. The @StaticRoutes annotation is just used for grouping several @ServeStatic annotations and could be left out in this example. Each controller call now has to have an annotation in order to be reachable. The name of the annotation is the HTTP method, or @Any, if it should match all HTTP methods. Its only mandatory parameter is the value, which resembles the URI—the second field in the routes. conf. All other parameters are optional. Especially interesting is the priority parameter, which can be used to give certain methods precedence. This allows a lower prioritized catchall controller like in the preceding example, but a special handling is required if the URI is called with the PUT method. You can easily check the correct behavior by using curl, a very practical command line HTTP client: curl -v localhost:9000/ This command should give you a result similar to this: > GET / HTTP/1.1 > User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18 > Host: localhost:9000 > Accept: */* > < HTTP/1.1 403 Forbidden < Server: Play! Framework;1.1;dev < Content-Type: text/html; charset=utf-8 < Set-Cookie: PLAY_FLASH=;Path=/ < Set-Cookie: PLAY_ERRORS=;Path=/ < Set-Cookie: PLAY_SESSION=0c7df945a5375480993f51914804284a3bb ca726-%00___ID%3A70963572-b0fc-4c8c-b8d5-871cb842c5a2%00;Path=/ < Cache-Control: no-cache < Content-Length: 32 < <h1>Reserved for administrator</h1> You can see the HTTP error message and the content returned. You can trigger a PUT request in a similar fashion: curl -X PUT -v localhost:9000/ > PUT / HTTP/1.1 > User-Agent: curl/7.21.0 (i686-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18 > Host: localhost:9000 > Accept: */* > < HTTP/1.1 200 OK < Server: Play! Framework;1.1;dev < Content-Type: text/plain; charset=utf-8 < Set-Cookie: PLAY_FLASH=;Path=/ < Set-Cookie: PLAY_ERRORS=;Path=/ < Set-Cookie: PLAY_SESSION=f0cb6762afa7c860dde3fe1907e8847347 6e2564-%00___ID%3A6cc88736-20bb-43c1-9d43-42af47728132%00;Path=/ < Cache-Control: no-cache < Content-Length: 16 Secret news here As you can see now, the priority has voted the controller method for the PUT method which is chosen and returned. There's more... The router module is a small, but handy module, which is perfectly suited to take a first look at modules and to understand how the routing mechanism of the Play framework works at its core. You should take a look at the source if you need to implement custom mechanisms of URL routing. Mixing the configuration file and annotations is possible You can use the router module and the routes file—this is needed when using modules as they cannot be specified in annotations. However, keep in mind that this is pretty confusing. You can check out more info about the router module at http://www.playframework.org/modules/router. Basics of caching Caching is quite a complex and multi-faceted technique, when implemented correctly. However, implementing caching in your application should not be complex, but rather the mindwork before, where you think about what and when to cache, should be. There are many different aspects, layers, and types (and their combinations) of caching in any web application. This recipe will give a short overview about the different types of caching and how to use them. You can find the source code of this example in the chapter2/caching-general directory. Getting ready First, it is important that you understand where caching can happen—inside and outside of your Play application. So let's start by looking at the caching possibilities of the HTTP protocol. HTTP sometimes looks like a simple protocol, but is tricky in the details. However, it is one of the most proven protocols in the Internet, and thus it is always useful to rely on its functionalities. HTTP allows the caching of contents by setting specific headers in the response. There are several headers which can be set: Cache-Control: This is a header which must be parsed and used by the client and also all the proxies in between. Last-Modified: This adds a timestamp, explaining when the requested resource had been changed the last time. On the next request the client may send an If-Modified- Since header with this date. Now the server may just return a HTTP 304 code without sending any data back. ETag: An ETag is basically the same as a Last-Modified header, except it has a semantic meaning. It is actually a calculated hash value resembling the resource behind the requested URL instead of a timestamp. This means the server can decide when a resource has changed and when it has not. This could also be used for some type of optimistic locking. So, this is a type of caching on which the requesting client has some influence on. There are also other forms of caching which are purely on the server side. In most other Java web frameworks, the HttpSession object is a classic example, which belongs to this case. Play has a cache mechanism on the server side. It should be used to store big session data, in this case any data exceeding the 4KB maximum cookie size. Be aware that there is a semantic difference between a cache and a session. You should not rely on the data being in the cache and thus need to handle cache misses. You can use the Cache class in your controller and model code. The great thing about it is that it is an abstraction of a concrete cache implementation. If you only use one node for your application, you can use the built-in ehCache for caching. As soon as your application needs more than one node, you can configure a memcached in your application.conf and there is no need to change any of your code. Furthermore, you can also cache snippets of your templates. For example, there is no need to reload the portal page of a user on every request when you can cache it for 10 minutes. This also leads to a very simple truth. Caching gives you a lot of speed and might even lower your database load in some cases, but it is not free. Caching means you need RAM, lots of RAM in most cases. So make sure the system you are caching on never needs to swap, otherwise you could read the data from disk anyway. This can be a special problem in cloud deployments, as there are often limitations on available RAM. The following examples show how to utilize the different caching techniques. We will show four different use cases of caching in the accompanying test. First test: public class CachingTest extends FunctionalTest { @Test public void testThatCachingPagePartsWork() { Response response = GET("/"); String cachedTime = getCachedTime(response); assertEquals(getUncachedTime(response), cachedTime); response = GET("/"); String newCachedTime = getCachedTime(response); assertNotSame(getUncachedTime(response), newCachedTime); assertEquals(cachedTime, newCachedTime); } @Test public void testThatCachingWholePageWorks() throws Exception { Response response = GET("/cacheFor"); String content = getContent(response); response = GET("/cacheFor"); assertEquals(content, getContent(response)); Thread.sleep(6000); response = GET("/cacheFor"); assertNotSame(content, getContent(response)); } @Test public void testThatCachingHeadersAreSet() { Response response = GET("/proxyCache"); assertIsOk(response); assertHeaderEquals("Cache-Control", "max-age=3600", response); } @Test public void testThatEtagCachingWorks() { Response response = GET("/etagCache/123"); assertIsOk(response); assertContentEquals("Learn to use etags, dumbass!", response); Request request = newRequest(); String etag = String.valueOf("123".hashCode()); Header noneMatchHeader = new Header("if-none-match", etag); request.headers.put("if-none-match", noneMatchHeader); DateTime ago = new DateTime().minusHours(12); String agoStr = Utils.getHttpDateFormatter().format(ago. toDate()); Header modifiedHeader = new Header("if-modified-since", agoStr); request.headers.put("if-modified-since", modifiedHeader); response = GET(request, "/etagCache/123"); assertStatus(304, response); } private String getUncachedTime(Response response) { return getTime(response, 0); } private String getCachedTime(Response response) { return getTime(response, 1); } private String getTime(Response response, intpos) { assertIsOk(response); String content = getContent(response); return content.split("n")[pos]; } } The first test checks for a very nice feature. Since play 1.1, you can cache parts of a page, more exactly, parts of a template. This test opens a URL and the page returns the current date and the date of such a cached template part, which is cached for about 10 seconds. In the first request, when the cache is empty, both dates are equal. If you repeat the request, the first date is actual while the second date is the cached one. The second test puts the whole response in the cache for 5 seconds. In order to ensure that expiration works as well, this test waits for six seconds and retries the request. The third test ensures that the correct headers for proxy-based caching are set. The fourth test uses an HTTP ETag for caching. If the If-Modified-Since and If-None- Match headers are not supplied, it returns a string. On adding these headers to the correct ETag (in this case the hashCode from the string 123) and the date from 12 hours before, a 302 Not-Modified response should be returned. How to do it... Add four simple routes to the configuration as shown in the following code: GET / Application.index GET /cacheFor Application.indexCacheFor GET /proxyCache Application.proxyCache GET /etagCache/{name} Application.etagCache The application class features the following controllers: public class Application extends Controller { public static void index() { Date date = new Date(); render(date); } @CacheFor("5s") public static void indexCacheFor() { Date date = new Date(); renderText("Current time is: " + date); } public static void proxyCache() { response.cacheFor("1h"); renderText("Foo"); } @Inject private static EtagCacheCalculator calculator; public static void etagCache(String name) { Date lastModified = new DateTime().minusDays(1).toDate(); String etag = calculator.calculate(name); if(!request.isModified(etag, lastModified.getTime())) { throw new NotModified(); } response.cacheFor(etag, "3h", lastModified.getTime()); renderText("Learn to use etags, dumbass!"); } } As you can see in the controller, the class to calculate ETags is injected into the controller. This is done on startup with a small job as shown in the following code: @OnApplicationStart public class InjectionJob extends Job implements BeanSource { private Map<Class, Object>clazzMap = new HashMap<Class, Object>(); public void doJob() { clazzMap.put(EtagCacheCalculator.class, new EtagCacheCalculator()); Injector.inject(this); } public <T> T getBeanOfType(Class<T>clazz) { return (T) clazzMap.get(clazz); } } The calculator itself is as simple as possible: public class EtagCacheCalculator implements ControllerSupport { public String calculate(String str) { return String.valueOf(str.hashCode()); } } The last piece needed is the template of the index() controller, which looks like this: Current time is: ${date} #{cache 'mainPage', for:'5s'} Current time is: ${date} #{/cache} How it works... Let's check the functionality per controller call. The index() controller has no special treatment inside the controller. The current date is put into the template and that's it. However, the caching logic is in the template here because not the whole, but only a part of the returned data should be cached, and for that a #{cache} tag used. The tag requires two arguments to be passed. The for parameter allows you to set the expiry out of the cache, while the first parameter defines the key used inside the cache. This allows pretty interesting things. Whenever you are in a page where something is exclusively rendered for a user (like his portal entry page), you could cache it with a key, which includes the user name or the session ID, like this: #{cache 'home-' + connectedUser.email, for:'15min'} ${user.name} #{/cache} This kind of caching is completely transparent to the user, as it exclusively happens on the server side. The same applies for the indexCacheFor() controller. Here, the whole page gets cached instead of parts inside the template. This is a pretty good fit for nonpersonalized, high performance delivery of pages, which often are only a very small portion of your application. However, you already have to think about caching before. If you do a time consuming JPA calculation, and then reuse the cache result in the template, you have still wasted CPU cycles and just saved some rendering time. The third controller call proxyCache() is actually the most simple of all. It just sets the proxy expire header called Cache-Control. It is optional to set this in your code, because your Play is configured to set it as well when the http.cacheControl parameter in your application.conf is set. Be aware that this works only in production, and not in development mode. The most complex controller is the last one. The first action is to find out the last modified date of the data you want to return. In this case it is 24 hours ago. Then the ETag needs to be created somehow. In this case, the calculator gets a String passed. In a real-world application you would more likely pass the entity and the service would extract some properties of it, which are used to calculate the ETag by using a pretty-much collision-safe hash algorithm. After both values have been calculated, you can check in the request whether the client needs to get new data or may use the old data. This is what happens in the request.isModified() method. If the client either did not send all required headers or an older timestamp was used, real data is returned; in this case, a simple string advising you to use an ETag the next time. Furthermore, the calculated ETag and a maximum expiry time are also added to the response via response.cacheFor(). A last specialty in the etagCache() controller is the use of the EtagCacheCalculator. The implementation does not matter in this case, except that it must implement the ControllerSupport interface. However, the initialization of the injected class is still worth a mention. If you take a look at the InjectionJob class, you will see the creation of the class in the doJob() method on startup, where it is put into a local map. Also, the Injector.inject() call does the magic of injecting the EtagCacheCalculator instance into the controllers. As a result of implementing the BeanSource interface, the getBeanOfType() method tries to get the corresponding class out of the map. The map actually should ensure that only one instance of this class exists. There's more... Caching is deeply integrated into the Play framework as it is built with the HTTP protocol in mind. If you want to find out more about it, you will have to examine core classes of the framework. More information in the ActionInvoker If you want to know more details about how the @CacheFor annotation works in Play, you should take a look at the ActionInvoker class inside of it. Be thoughtful with ETag calculation Etag calculation is costly, especially if you are calculating more then the last-modified stamp. You should think about performance here. Perhaps it would be useful to calculate the ETag after saving the entity and storing it directly at the entity in the database. It is useful to make some tests if you are using the ETag to ensure high performance. In case you want to know more about ETag functionality, you should read RFC 2616. You can also disable the creation of ETags totally, if you set http.useETag=false in your application.conf. Use a plugin instead of a job The job that implements the BeanSource interface is not a very clean solution to the problem of calling Injector.inject() on start up of an application. It would be better to use a plugin in this case.
Read more
  • 0
  • 0
  • 3542

article-image-introduction-rhomobile
Packt
21 Jul 2011
6 min read
Save for later

An introduction to Rhomobile

Packt
21 Jul 2011
6 min read
The Rhomobile family Rhomobile Inc. is a computer software company that provides leading products for building the new generation of mobile applications. It offers an open-source Ruby-based mobile development framework for business mobility solutions through its four major products Rhodes, RhoSync, Rhohub, and RhoGallery. Rhodes Rhodes is an open source framework by Rhomobile. It develops native applications for almost all smart phones. The applications built through Rhodes are pure native applications and use device capabilities such as GPS, PIM contacts and calendar, camera, native mapping, push, barcode, signature capture, and Bluetooth. Rhodes accelerates the development of mobile applications without compromising on its portability. This framework is similar to the popular Rails framework. It is based on Model view Controller and has inbuilt Object Relational Manager (ORM) called Rhom that is similar to active Record in Rails. Most user interface customization can be done in HTML templates (ERB, eruby files). A single set of source written with Rhodes can be compiled to run across all of the supported smart phones. This means that we will have the same code base for all your devices. RhoSync RhoSync is a standalone mobile sync server that keeps enterprise application data up to date and available on users' smart phones. Enterprise apps require local synchronized data to be used most of the time. The information is stored locally on a users' device and is available to them even in offline mode. It is very easy to write a source adapter as RhoSync generates most of the code while creating the source adapter. The source adapter can also be used to Create, Read, Update, and Delete (CRUD) operations on a model. Rhosync uses Redis, which is a NoSql Key Value store for data caching. This makes Rhosync more scalable. RhoSync performs its push-based sync using the native smartphone push SDKs. It uses new advanced BlackBerry Enterprise Server and iPhone 3.0 SDKs for Push. It uses BES Push and iPhone Push for synchronization, allowing real-time updates of backend application information. RhoHub RhoHub is a hosted development environment for Rhodes and Rhosync. The RhoSync application will be deployed on the famous Ruby cloud Heroku with the interface of RhoHub. RhoHub enables git-powered source control and collaboration with your team. It allows us to directly build an application for different smart phones without installing SDKs. It makes the process of the build very smooth since we don't have to install any development toolkits. It is only a one click process that automatically creates a build for most of the smart phones. Rhohub provides us with the following functionalities: Creating a build for a Rhodes application Deploying the Rhosync application to the cloud Providing version control with git Managing collaborators RhoGallery RhoGallery provides a hosted mobile app management solution. It allows administrators to manage the set of apps exposed to their users. It also makes it easy for them to get mobile apps onto their devices. It enables users to launch all of their important enterprise apps from a single place. RhoGallery consists of a management console for "app galleries" on RhoHub, as well as a RhoGallery App that users load onto their devices. Even for an individual developer with one or a few apps, RhoGallery makes it easy to expose those apps to their users. RhoGallery handles inviting the users and determining the appropriate downloads to provide to them. RhoGallery provides the following functionalities: Administrator management of exposed apps to end users Central user launching of exposed apps Automatic provisioning of appropriate apps for end users Why Rhomobile is cutting edge The following features give a cutting edge to Rhomobile in mobile application development: Model View Controller: Most of the other frameworks available in the market are based on HTML and JavaScript. However, as Rhodes is a Ruby-based framework and its structure is similar to the popular framework Rails, it also supports Model View Controller, so code written with Rhodes is more structured and easy to understand. Cross Platform Support for All Devices: Rhodes supports the following devices: Android, Windows Mobile, BlackBerry, and iphone. The best thing is you have a single code base from which you can build applications for different smart phones. It does not work in a traditional way in that we have to write separate code for different types of phones. Offline Capabilities using Rhosync: Rhomobile supports local synchronization of data. As we can synchronize the data using Rhosync it provides offline Capabilities. It can work even if you are offline. Object Relational Manager: Rhodes provides an inbuilt Object Relational Manager called Rhom. It is similar to Active Record in Rails but with basic functionality only. It helps us to write queries without thinking about which database is being used by phone. Rapid Development: One of the most interesting features of Rhodes is that it imposes some fairly serious constraints on how you structure the applications that help us for rapid development. Rhomobile products are properly structured and well organized, which enforce us to do rapid development. Rhodes is very comfortable, familiar, and massively productive. Scalable Sync Server: The Sync Server uses a NoSql Database which makes it scalable. Specifically, it is the only sync server that has a built-in "no SQL" Redis key value store, making it more scalable than other sync servers which offer internal relational database servers for caching. RhoSync also performs its push-based sync using the native smart phone push SDKs, which no other sync server does. Liberal use of code generation: Rhodes/RhoSync can write a lot of code for you. For example, when you need a class to represent a table in your database, you don't have to write most of the methods. Rhodes even offers an application generator that creates an initial app based on the structure of your models or business objects in your app. It's very similar to the scaffolding offered by most modern web frameworks with basic list/create/read/update/delete objects functionality. For each basic CRUD action, views in HTML are also offered. You'll find that you're writing only a fraction of code compared to other frameworks. Metadata: Every enterprise application that is used to run a company's core business has a different schema for its business objects. For example, every application has a varying and customized structure that changes with time. It is not possible to install the client application again and again for a small change. The Metadata framework provides a way to handle the view from the Rhosync server. It also provides validation and a custom template. Hosted Development and Build: Rhomobile also provides a hosted management and Build through Rhohub. We can deploy a Rhosync app and build our Rhodes code for different phones with it.
Read more
  • 0
  • 0
  • 3063

article-image-integrating-biztalk-server-and-microsoft-dynamics-crm
Packt
20 Jul 2011
7 min read
Save for later

Integrating BizTalk Server and Microsoft Dynamics CRM

Packt
20 Jul 2011
7 min read
What is Microsoft Dynamics CRM? Customer relationship management is a critical part of virtually every business. Dynamics CRM 2011 offers a solution for the three traditional areas of CRM: sales, marketing, and customer service. For customers interested in managing a sales team, Dynamics CRM 2011 has a strong set of features. This includes organizing teams into territories, defining price lists, managing opportunities, maintaining organization structures, tracking sales pipelines, enabling mobile access, and much more. If you are using Dynamics CRM 2011 for marketing efforts, then you have the ability to import data from multiple sources, plan campaigns and set up target lists, create mass communications, track responses to campaigns, share leads with the sales team, and analyze the success of a marketing program. Dynamics CRM 2011 also serves as a powerful hub for customer service scenarios. Features include rich account management, case routing and management, a built-in knowledge base, scheduling of call center resources, scripted Q&A workflows called Dialogs, contract management, and more. Besides these three areas, Microsoft pitches Dynamics CRM as a general purpose application platform called xRM, where the "X" stands for any sort of relationship management. Dynamics CRM has a robust underlying framework for screen design, security roles, data auditing, entity definition, workflow, and mobility, among others. Instead of building these foundational aspects into every application, we can build our data-driven applications within Dynamics CRM. Microsoft has made a big move into the cloud with this release of Dynamics CRM 2011. For the first time in company history, a product was released online (Dynamics CRM Online) prior to on-premises software. The hosted version of the application runs an identical codebase to the on-premises version meaning that code built to support a local instance will work just fine in the cloud. In addition to the big play in CRM hosting, Microsoft has also baked Windows Azure integration into Dynamics CRM 2011. Specifically, we now have the ability to configure a call-out to an Azure AppFabric Service Bus endpoint. To do this, the downstream service must implement a specific WCF interface and within CRM, the Azure AppFabric plugin is configured to call that downstream service through the Azure AppFabric Service Bus relay service. For BizTalk Server to accommodate this pattern, we would want to build a proxy service that implements the required Dynamics CRM 2011 interface and forwards requests into a BizTalk Server endpoint. This article will not demonstrate this scenario, however, as the focus will be on integrating with an onpremises instance only. Why Integrate Dynamics CRM and BizTalk Server? There are numerous reasons to tie these two technologies together. Recall that BizTalk Server is an enterprise integration bus that connects disparate applications. There can be a natural inclination to hoard data within a particular application, but if we embrace real-time message exchange, we can actually have a more agile enterprise. Consider a scenario when a customer's full "contact history" resides in multiple systems. The Dynamics CRM 2011 contact center may only serve a specific audience, and other systems within the company hold additional details about the company's customers. One design choice could be to bulk load that information into Dynamics CRM 2011 on a scheduled interval. However, it may be more effective to call out to a BizTalk Server service that aggregates data across systems and returns a composite view of a customer's history with a company. In a similar manner, think about how information is shared between systems. A public website for a company may include a registration page where visitors sign up for more information and deeper access to content. That registration event is relevant to multiple systems within the company. We could send that initial registration message to BizTalk Server and then broadcast that message to the multiple systems that want to know about that customer. A marketing application may want to respond with a personalized email welcoming that person to the website. The sales team may decide to follow up with that person if they expressed interest in purchasing products. Our Dynamics CRM 2011 customer service center could choose to automatically add the registration event so that it is ready whenever that customer calls in. In this case, BizTalk Server acts as a central router of data and invokes the exposed Dynamics CRM services to create customers and transactions. Communicating from BizTalk Server to Dynamics CRM The way that you send requests from BizTalk Server to Dynamics CRM 2011 has changed significantly in this release. In the previous versions of Dynamics CRM, a BizTalk "send" adapter was available for communicating with the platform. Dynamics CRM 2011 no longer ships with an adapter and developers are encouraged to use the WCF endpoints exposed by the product. Dynamics CRM has both a WCF REST and SOAP endpoint. The REST endpoint can only be used within the CRM application itself. For instance, you can build what is called a web resource that is embedded in a Dynamics CRM page. This resource could be a Microsoft Silverlight or HTML page that looks up data from three different Dynamics CRM entities and aggregates them on the page. This web resource can communicate with the Dynamics CRM REST API, which is friendly to JavaScript clients. Unfortunately, you cannot use the REST endpoint from outside of the Dynamics CRM environment, but because BizTalk cannot communicate with REST services, this has little impact on the BizTalk integration story. The Dynamics CRM SOAP API, unlike its ASMX web service predecessor, is static and operates with a generic Entity data structure. Instead of having a dynamic WSDL that exposes typed definitions for all of the standard and custom entities in the system, the Dynamics CRM 2011 SOAP API has a set of operations (for example, Create, Retrieve) that function with a single object type. The Entity object has a property identifying which concrete object it represents (for example, Account or Contract), and a name/value pair collection that represents the columns and values in the object it represents. For instance, an Entity may have a LogicalName set to "Account" and columns for "telephone1", "emailaddress", and "websiteurl." In essence, this means that we have two choices when interacting with Dynamics CRM 2011 from BizTalk Server. Our first option is to directly consume and invoke the untyped SOAP API. Doing this involves creating maps from a canonical schema to the type-less Entity schema. In the case of doing a Retrieve operation, we may also have to map the type-less Entity message back to a structured message for more processing. Below, we will walk through an example of this. The second option involves creating a typed proxy service for BizTalk Server to invoke. Dynamics CRM has a feature-rich Solution Development Kit (SDK) that allows us to create typed objects and send them to the Dynamics CRM SOAP endpoint. This proxy service will then expose a typed interface to BizTalk that operates as desired with a strongly typed schema. An upcoming exercise demonstrates this scenario. Which choice is best? For simple solutions, it may be fine to interact directly with the Dynamics CRM 2011 SOAP API. If you are updating a couple fields on an entity, or retrieving a pair of data values, the messiness of the untyped schema is worth the straightforward solution. However, if you are making large scale changes to entities, or getting back an entire entity and publishing to the BizTalk bus for more subscribers to receive, then working strictly with a typed proxy service is the best route. However, we will look at both scenarios below, and you can make that choice for yourself. Integrating Directly with the Dynamics CRM 2011 SOAP API In the following series of steps, we will look at how to consume the native Dynamics CRM SOAP interface in BizTalk Server. We will first look at how to query Dynamics CRM to return an Entity. After that, we will see the steps for creating a new Entity in Dynamics CRM. Querying Dynamics CRM from BizTalk Server In this scenario, BizTalk Server will request details about a specific Dynamics CRM "contact" record and send the result of that inquiry to another system.
Read more
  • 0
  • 0
  • 5601
article-image-getting-started-aws-and-amazon-ec2
Packt
20 Jul 2011
4 min read
Save for later

Getting Started with AWS and Amazon EC2

Packt
20 Jul 2011
4 min read
  Amazon Web Services: Migrate your .NET Enterprise Application to the Amazon Cloud Evaluate your Cloud requirements and successfully migrate your Enterprise .NET application to the Amazon Web Services Platform with this book and eBook         Read more about this book       (For more resources on this subject, see here.) Creating your first AWS account Well, here you are, ready to log in; create your first AWS account and get started! AWS lives at http://aws.amazon.com, so browse to this location and you will be greeted with the Amazon Web Services home page. From November 1st, 2010, Amazon has provided a free usage tier, which is currently displayed prominently on the front page. So, to get started click on the Sign Up Now button. You will be prompted with the Web Services Sign In screen. Enter the e-mail address that you would like to be associated with your AWS account and select I am a new user. When you have entered your e-mail address, click on the Sign in using our secure server button. Multi-factor authentication One of the things worth noting about this sign in screen is the Learn more comment at the bottom of the page, which mentions multi-factor authentication. Multi-factor authentication can be useful where organizations are required to use a more secure form of remote access. If you would like to secure your AWS account using multi-factor authentication this is now an option with AWS. To enable this, you will need to continue and create your AWS account. After your account has been created, go to the following address http://aws.amazon.com/ mfa/#get_device and follow the instructions for purchasing a device: Once you have the device in hand, you'll need to log in again to enable it: You will then be prompted with the extra dialog when signing in: Registration and privacy details Once you have clicked on the Sign in using our secure server button, you will be presented with the registration screen. Enter your full name and password that you would like to use: Note the link to the Privacy Notice at the bottom of the screen. You should be aware that the privacy notice is the same privacy notice used for the Amazon.com bookstore and website, which essentially means that any information you provide to Amazon through AWS may be correlated to purchases made on the Amazon bookstore and website. (Move the mouse over the image to enlarge it.) Fill out your contact details, agree to the AWS Customer Agreement, and complete the Security Check at the bottom of the form: If you are successful, you will be presented with the following result: AWS customer agreement Please note that the AWS Customer agreement is worth reading, with the full version located at http://aws.amazon.com/agreement. The agreement covers a lot of ground, but a couple of sections that are worth noting are: Section 10.2 – Your Applications, Data, and Content This section specifically states that you are the intellectual property and proprietary rights owner of all data and applications running under this account. However, the same section specifically gives the right to Amazon to hand over your data to a regulatory body, or to provide your data at the request of a court order or subpoena. Section 14.2 – Governing Law This section states that by agreeing to this agreement, you are bound by the laws of the State of Washington, USA, which—read in conjunction with section 10.2— suggests that any actions that fall out of section 10.2 will be initiated from within the State of Washington. Section 11.2 – Applications and Content This section may concern some users as it warrants that you (as the AWS user) are solely responsible for the content and security of any data and applications running under your account. I advise that you seek advice from your company's legal department prior to creating an account, which will be used for your enterprise.
Read more
  • 0
  • 0
  • 3188

article-image-communicating-dynamics-crm-biztalk-server
Packt
20 Jul 2011
6 min read
Save for later

Communicating from Dynamics CRM to BizTalk Server

Packt
20 Jul 2011
6 min read
Microsoft BizTalk 2010: Line of Business Systems Integration A practical guide to integrating Line of Business systems with BizTalk Server 2010 There are three viable places where Dynamics CRM can communicate with BizTalk Server. First, a Dynamics CRM form is capable of executing client-side JavaScript at various points in the form lifecycle. One can definitely use JavaScript to invoke web services, including web services exposed by BizTalk Server. However, note that JavaScript invocation of web services is typically synchronous and could have a negative impact on the user experience if a form must constantly wait for responses from distributed services. Also, JavaScript that runs within Dynamics CRM is clientside and tied directly to the page on which it resides. If we programmatically interact with a Dynamics CRM entity, then any code existing in the client-side script will not get invoked. For instance, if after an "account" record is created we send a message, via JavaScript, to BizTalk, this logic would not fire if we created an "account" record programmatically. The second place where Dynamics CRM can communicate with BizTalk Server is through workflows. A workflow in Dynamics CRM is an automated process where a set of steps is executed according to rules that we define. For example, when a sales opportunity is closed, we run a workflow that adds a message to the customer record, notifies all parties tied to the opportunity, and sends a polite email to the lost prospect. Workflows are based on Windows Workflow 4.0 technology and can be built either in the Dynamics CRM application itself or within Visual Studio 2010. The Dynamics CRM web application allows us to piece together workflows using previously registered workflow steps. If we need new workflow steps or need to construct something complex, we can jump into Visual Studio 2010 and define the workflow there. Why would we choose to use a workflow to send a message to BizTalk Server? If you have a long-running process that can either be scheduled or executed on demand and want the option for users to modify the process, the workflow may be the right choice. The final strategy for communicating between Dynamics CRM and BizTalk Server is to use plugins. Plugins are server-based application extensions that execute business logic and get tied directly to an entity. This means that they are invoked whether we work in the Dynamics CRM web interface or through the API. I can run a plugin both synchronously and asynchronously, depending on the situation. For instance, if we need to validate the data on a record prior to saving it, we can set a plugin to run before the "save" operation is committed and provide some user feedback on the invalid information. Or, we could choose to asynchronously call a plugin after a record is saved and transmit data to our service bus, BizTalk Server. In the following exercise, we will leverage plugins to send data from Dynamics CRM to BizTalk Server. Integration with BizTalk Server In this first walkthrough, we will build a plugin that communicates from Dynamics CRM to a BizTalk Server located. An event message will be sent to BizTalk whenever a change occurs on an Account record in Dynamics CRM. Setup This exercise leverages a BizTalk Server project already present in your Visual Studio 2010 solution. We are going to publish a web service from BizTalk Server that takes in a message and routes it to a BizTalk send port that writes the message to the file system. If you have not already done so, go to the code package and navigate to C:LOBIntegrationChapter03Chapter3-DynamicsCRM and open the Visual Studio 2010 solution file named Chapter3-DynamicsCRM.sln. Find the BizTalk Server project named Chapter3-DynamicsCRM.AcctRouting and open it. The code package includes a custom schema named AccountEventChange_XML.xsd and notice which elements we want from Dynamics CRM 2011 when an account changes. The first element, EventSource, is used to designate the source of the change event, as there may be multiple systems that share changes in an organization's accounts. This BizTalk project should be set to deploy to a BizTalk application named Chapter3. Build and deploy the project to the designated BizTalk Server. After confirming a successful deployment, launch the BizTalk WCF Service Publishing Wizard. We are going to use this schema to expose a web service entry point into BizTalk Server that Dynamics CRM 2011 can invoke. On the WCF Service Type wizard page, select a WCF-BasicHttp adapter and set the service to expose metadata and have the wizard generate a receive location for us in the Chapter3 application: On the Create WCF Service wizard page, choose to Publish schemas as WCF service. This option gives us fine-grained control over the naming associated with our service. On the next page, delete the two-way operation already present in the service definition. Rename the topmost service definition to AccountChangeService and assign the service the same name. Right-click the service and create a new one-way operation named PublishAccountChange. Right-click the Request message of the operation and choose the AccountChangeEvent message from our BizTalk Project's DLL: On the following wizard page, set the namespace of the service to http://Chapter3/AccountServices. Next, set the location of our service to http://localhost/AccountChangeService and select the option to allow anonymous access to the generated service. Finally, complete the wizard by clicking the Create button on the final wizard page. Confirm that the wizard successfully created both an IIS-hosted web service, and a BizTalk receive port/location. Ensure that the IIS web service is running under an Application Pool that has permission to access the BizTalk databases. In order to test this service, first, go to the BizTalk Server Administration Console and locate the Chapter3 application. Right click the Send Ports folder and create a new, static one-way send port named Chapter3.SendAccountChange.FILE. Set the send port to use the FILE adapter and select the FileDropDropCustomerChangeEvent folder that is present in the code package: This send port should listen for all account change event messages, regardless of which receive location (and system) that they came from. Go to the Filters tab of this send port. Set the filter Property to BTS.MessageType and filter Value to http://Chapter3-DynamicsCRM.AcctRouting.AccountChangeEvent_XML#AccountChangeEvent. All that remains is to test our service. Open the WCF Test Client application and add a new service reference to http://localhost/AccountChangeService/AccountChangeService.svc. Invoke the PublishAccountChange method and, if everything is configured correctly, we will see a message emitted by BizTalk Server that matches our service input parameters: (Move the mouse over the image to enlarge.) We now are sufficiently ready to author the Dynamics CRM plugin, which calls this BizTalk service.  
Read more
  • 0
  • 0
  • 3274
Modal Close icon
Modal Close icon