tag:blogger.com,1999:blog-1177608463175933012024-03-16T02:10:12.848+01:00Jamie Craane's BlogMy views, thoughts and experiences about Enterprise Application Development.jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.comBlogger65125tag:blogger.com,1999:blog-117760846317593301.post-73659898232611590212020-12-10T23:24:00.002+01:002020-12-10T23:24:36.210+01:00Blog has moved to https://jamiecraane.dev/<p>My personal blog has moved to <a href="https://jamiecraane.dev/">https://jamiecraane.dev/</a><br /></p>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com2tag:blogger.com,1999:blog-117760846317593301.post-18161970241856706512016-12-12T20:02:00.000+01:002016-12-12T20:02:19.553+01:00AWS tutorial: Retrieve items from DynamoDB using Lambda and API Gateway<h2>
<div style="font-family: Helvetica; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><b>Introduction</b></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">Part 1: <a href="http://jcraane.blogspot.nl/2016/12/aws-lambdajava-dynamodb-and-api-gateway.html">http://jcraane.blogspot.nl/2016/12/aws-lambdajava-dynamodb-and-api-gateway.html</a></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
source code: <a href="https://github.com/jcraane/LambdaDynamoDBApiGateway">https://github.com/jcraane/LambdaDynamoDBApiGateway</a></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">In the previous tutorial I showed you how to use AWS Lambda and API Gateway to insert items in a DynamoDB table. The example implemented a function which stored the location of the user. In this tutorial we create a Lambda function which retrieves this data from the DynamoDB table and expose this functionality over HTTP using API Gateway.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><b>Create a DynamoDB Global Secondary Index</b></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">The DeviceLocation DynamoDB table uses the id as partition key. To retrieve the locations for a given device, a global secondary index must be created to query on deviceId.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">1. Open the AWS console and navigate to the DynamoDB section.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">2. Select the DeviceLocation table and click the Indexes tab.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">3. Select Create Index.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">4. Use deviceId as the partition key, use 1 for read/write capacity units and click create. See the create_dynamodb_index screenshot.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWuAG-JT5khJR1hd-i1yiw1BCqdzkiGkn3k0BoJgyhUAnlVhHBxYRPk6BIM5Bp6IO_u8tS6w7L95cglvw1oMLqo3L3FJ9bF9QBGApP1OqQryfb-pLmg5iLRFhL8x91VuglICS8zZSWD_I/s1600/Screen+Shot+2016-12-12+at+16.17.31.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="586" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWuAG-JT5khJR1hd-i1yiw1BCqdzkiGkn3k0BoJgyhUAnlVhHBxYRPk6BIM5Bp6IO_u8tS6w7L95cglvw1oMLqo3L3FJ9bF9QBGApP1OqQryfb-pLmg5iLRFhL8x91VuglICS8zZSWD_I/s640/Screen+Shot+2016-12-12+at+16.17.31.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: Helvetica; font-size: 16px; text-align: start;">create_dynamodb_index</span></td></tr>
</tbody></table>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<br /></div>
<div style="font-family: Helvetica; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><b>Create the implementation</b></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">1. Create a new class named RetrieveLocationRequest with one field named “deviceId” with type String. This class holds the parameters which are used as query input to the DynamoDB table.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">2. Create a new class named RetrieveLocationResponse with a field named “locations” of type List<devicelocation>. This class will hold the data returned to the consumer of the Lambda function.</devicelocation></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">3. Initialize the locations field to: new ArrayList<>() since we are going to add DeviceLocation objects to it.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">4. Create a new class named RetrieveLocationFunction which implements the com.amazonaws.services.lambda.runtime.RequestHandler<retrievelocatonrequest retrievelocationresponse=""> interface.</retrievelocatonrequest></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">The RetrieveLocationFunction is the implementation of our Lambda function which queries DynamoDB using the given deviceId. It retrieves all locations for the given device.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">Copy the following code and paste this in the handleRequest method of the RetrieveLocationFunction class. Make sure the region used here is the same region as the region of the DynamoDB table!</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">final AmazonDynamoDBClient client = new AmazonDynamoDBClient(new EnvironmentVariableCredentialsProvider());</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">client.withRegion(Regions.EU_CENTRAL_1); // specify the region you created the table in.</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">final DynamoDB dynamoDB = new DynamoDB(client);</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-family: Courier New, Courier, monospace;"><span style="font-kerning: none;"></span><br /></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">System.out.println("input = " + input); // Pure for testing. Do not use System.out in production code</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-family: Courier New, Courier, monospace;"><span style="font-kerning: none;"></span><br /></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">final Table table = dynamoDB.getTable("DeviceLocation");</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">final Index index = table.getIndex("deviceId-index");</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">final ItemCollection<queryoutcome> items = index.query("deviceId", input.getDeviceId());</queryoutcome></span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-family: Courier New, Courier, monospace;"><span style="font-kerning: none;"></span><br /></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">final RetrieveLocationResponse response = new RetrieveLocationResponse();</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">for (final Item item : items) {</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> final DeviceLocation deviceLocation = new DeviceLocation();</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> deviceLocation.setDeviceId(item.getString("deviceId"));</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> deviceLocation.setLat(item.getDouble("lat"));</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> deviceLocation.setLng(item.getDouble("lng"));</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> response.getLocations().add(deviceLocation);</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-family: Courier New, Courier, monospace;"><span style="font-kerning: none;"></span><br /></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">return response;</span></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><b>Create the Lambda function</b></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">After the implementation is ready we need to upload the function and configure it in AWS.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">1. Run the Gradle “clean build” task to create the zip distribution which holds our code and dependencies.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">2. Open the AWS console and navigate to the Lambda section.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">3. Select “Create a Lambda function” and select Blank Function.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">4. Click Next.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">5. As name specify “retrieveLocations” and as runtime select Java 8.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">6. Upload the PROJECT/build/distributions/DISTRIBUTION_NAME.zip file</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">7. Use com.example.persister.RetrieveLocationFunction as the Handler</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">8. Use the existing lambda_location_persister role create in <a href="http://jcraane.blogspot.nl/2016/12/aws-lambdajava-dynamodb-and-api-gateway.html">part 1</a> of this series.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">9. Leave the rest default and click Next.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">9. Click Create Function.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">10. To test the function click Test and use the following test data (replace DEVICE_ID with the deviceId of a record in the table. Refer to <a href="http://jcraane.blogspot.nl/2016/12/aws-lambdajava-dynamodb-and-api-gateway.html">part 1</a> to insert data in the DeviceLocation table):</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> "deviceId": “DEVICE_ID”</span></span></div>
<div style="font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><b>Exposing the functionality using API gateway</b></span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">The retrieveLocations function will be exposed using an HTTP GET method using API Gateway.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">1. Open the AWS console and navigate to API Gateway.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">2. Create a new GET method under the deviceLocation resource.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">3. As Integration Type choose Lambda Function and select the region the Lambda Function was created in.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">4. Specify retrieveLocations as the name and click Save.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">The deviceId is passed in as a query parameter in the URL and must be mapped as input to the Lambda function.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal; min-height: 19px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">1. Open the Method Request settings and open URL Query String Parameters.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">2. Add a query parameter named deviceId.</span></div>
<div style="font-family: Helvetica; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">3. Open the Integration Request settings and open Body Mapping Templates.</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none; -webkit-text-stroke-color: rgb(0, 0, 0); font-family: Helvetica; line-height: normal;">4. Choose the </span><span style="-webkit-font-kerning: none; -webkit-text-stroke-color: rgb(0, 0, 0);">optio</span><span style="-webkit-font-kerning: none; -webkit-text-stroke-color: rgb(0, 0, 0);">n:</span><span style="background-color: white; font-kerning: none;"> When there are no templates defined (recommended)</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">5. Add a mapping template for: application/json</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">6. Add the following template to map the deviceId URL query parameter to the Lambda input (see screenshot body_mapping).</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal; min-height: 18px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">{</span></span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;"> "deviceId": "$input.params('deviceId')"</span></span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="-webkit-font-kerning: none;"><span style="font-family: Courier New, Courier, monospace;">}</span></span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal; min-height: 18px;">
<span style="font-kerning: none;"></span><br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimo5COxKdDG6Mo1P72KqnARb_f08Yyf-hKsGka2tHGQt5o4f912JVqbMc2P6NPzczkMdomht7RDVHvGCdO6m4FNx9ICzlkrSwsQSAIWQpau2xuBa1K5PQ5MDiZmfq0wbpIfyK5No9KGIU/s1600/Screen+Shot+2016-12-12+at+19.55.43.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="518" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimo5COxKdDG6Mo1P72KqnARb_f08Yyf-hKsGka2tHGQt5o4f912JVqbMc2P6NPzczkMdomht7RDVHvGCdO6m4FNx9ICzlkrSwsQSAIWQpau2xuBa1K5PQ5MDiZmfq0wbpIfyK5No9KGIU/s640/Screen+Shot+2016-12-12+at+19.55.43.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">body_mapping</td></tr>
</tbody></table>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal; min-height: 18px;">
<br /></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal; min-height: 18px;">
<br /></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">7. Click Save.</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">8. Click Test, add a known deviceId and Click the Test button. You should see the output of the Lambda function.</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">9. Click Actions -> Deploy API to deploy your api.</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">10. You function should now be publicly accessible.</span></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal; min-height: 18px;">
<span style="font-kerning: none;"></span><br /></div>
<div style="-webkit-text-stroke-color: rgb(51, 51, 51); -webkit-text-stroke-width: initial; background-color: white; font-family: Arial; font-size: 16px; font-weight: normal; line-height: normal;">
<span style="font-kerning: none;">Make sure you delete your resources when you are done with the tutorial to prevent unwanted billing.</span></div>
</h2>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com1tag:blogger.com,1999:blog-117760846317593301.post-19964799442939331082016-12-02T19:09:00.003+01:002016-12-12T20:02:58.932+01:00AWS Lambda/Java, DynamoDB and Api gateway integration<h2>
Introduction</h2>
Part 2: <a href="http://jcraane.blogspot.nl/2016/12/aws-tutorial-retrieve-items-from.html">http://jcraane.blogspot.nl/2016/12/aws-tutorial-retrieve-items-from.html</a><br />
<br />
In this post I am going through a full (Java) example of integrating AWS Lambda, DynamoDb and Api Gateway to create a function and expose this function as a HTTP resource for other parties to consume.<br />
<br />
Before we dive into the details I will give a brief overview of the AWS services used in this example (as taken from the AWS documentation):<br />
<br />
<ul>
<li>AWS Lambda. AWS Lambda is a compute service that runs developers' code in response to events and automatically manages the compute resources for them, making it easy to build applications that respond quickly to new information.</li>
<li>DynamoDB: Fast and flexible, managed, NoSql database.</li>
<li>Api Gateway: Amazon API Gateway is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale.</li>
</ul>
<br />
In this example we are going to create a lambda function which tracks the location (latitude and longitude) of a specific mobile device. The data flow looks like this:<br />
<br />
mobile device -> HTTP POST -> Api Gateway -> recordLocation (Lambda function) -> DynamoDb (store location)<br />
<h2>
Creating the application</h2>
Prerequisites:<br />
<br />
<ul>
<li>IntelliJ Idea is used for this example but any IDE will do. Gradle is used for the build system.</li>
<li>AWS account to actually deploy and run the example.</li>
<li>After you are done with the example, delete any AWS resources you have created to prevent unnecessary billing.</li>
</ul>
<br />
For the implementation of the Lambda function we use the AWS Java SDK.<br />
<br />
1. In IntelliJ, Select File -> New project and choose Gradle with the Java library. Click Next<br />
2. groupId=com.example, artifactId=locationpersister. Click Next.<br />
3. Choose a Java 8 IDE and Click Next, click Finish.<br />
4. Create the src/main/java folder if it does not exist already.<br />
5. Open de build.gradle file and add the following dependencies:<br />
<blockquote class="tr_bq">
compile 'com.amazonaws:aws-lambda-java-core:1.1.0'<br />
compile 'com.amazonaws:aws-lambda-java-events:1.1.0'</blockquote>
6. Add the following code to the build.gradle file:<br />
<blockquote class="tr_bq">
task buildZip(type: Zip) {<br />
from compileJava<br />
from processResources<br />
into('lib') {<br />
from configurations.runtime<br />
}<br />
}<br />
build.dependsOn buildZip</blockquote>
The above code creates a zip archive when the build task is triggered. The zip file can be uploaded directly to AWS Lambda.<br />
<br />
7. Create a class com.example.persister.DeviceLocation with the members: lat (double), lng (double) and deviceId (string). This class holds the data that gets submitted to the Lambda function.<br />
8. Create a new class com.example.persister.LocationPersisterFunction. This class will hold the implementation of the Lambda function.<br />
9. Make the LocationPersisterFunction implement the com.amazonaws.services.lambda.runtime.RequestHandler<devicelocation void=""> interface.</devicelocation><br />
This interface defines the handleRequest function which is executed when the Lambda function is triggered. The handleRequest function takes two parameters: the input (which is of DeviceLocation type and is passed-in when the function is invoked Context object).<br />
<br />
<i>Creating the DynamoDb table</i><br />
<i><br /></i>
To store the data in DynamoDB we need to create a table.<br />
<br />
1. Open the AWS console and navigate to the DynamoDB section.<br />
2. Click create Table and for the name use: "DeviceLocation". Type id (string field) to use as a partition key and do not specify a sort key. Leave everything default and click Create.<br />
3. Please note that the table is created in the selected regio. If you click on the table and look at the details you can see the region of the table.<br />
<br />
<i>Create the DeviceLocation class</i><br />
<br />
The DeviceLocation class holds the input which is passed to the Lambda function.<br />
1. Create a new class named DeviceLocation with the following fields: id (string), lat (double) and lng (double)<br />
2. Make sure the class contains both setters and getters. The setters are used by AWS Lambda to populate this object based on the passed in JSON when calling the Lambda function.<br />
<br />
<i>Implementing the Lambda function</i><br />
<br />
1. Open the LocationPersisterFunction<br />
2. Add the following code to the body of the handleRequest method:<br />
<blockquote class="tr_bq">
final AmazonDynamoDBClient client = new AmazonDynamoDBClient(new EnvironmentVariableCredentialsProvider());<br />
client.withRegion(Regions.EU_WEST_1); // specify the region you created the table in.<br />
DynamoDB dynamoDB = new DynamoDB(client);<br />
Table table = dynamoDB.getTable("DeviceLocation");<br />
final Item item = new Item()<br />
.withPrimaryKey("id", UUID.randomUUID().toString()) // Every item gets a unique id<br />
.withString("deviceId", input.getDeviceId())<br />
.withDouble("lat", input.getLat())<br />
.withDouble("lng", input.getLng());<br />
table.putItem(item);<br />
return null;</blockquote>
3. Make sure you change the region to match the region you created the table in.<br />
4. The above code gets a reference to the DynamoDB DeviceLocation table, creates an item and persist it.<br />
5. Execute the gradle build task to create a zip-archive or our code.<br />
5. Now that the implementation is complete we are ready to create our AWS Lambda function.<br />
<br />
<i>Creating out Lambda function</i><br />
<i><br /></i>
1. Open the AWS console and navigate to the Lambda section.<br />
2. Select Blank function and click next (we do not create a trigger at this stage).<br />
3. As name choose: persistDeviceLocation and select Java 8 as the runtime<br />
4. Upload the <project>/build/distributions/locationpersister-1.0-SNAPSHOT.zip file</project><br />
5. In the Handler field specify the fully qualified classname which implements our handler: com.example.persister.LocationPersisterFunction<br />
6. In the Role field select to create a custom role. The create role form is opened. Use lambda_location_persister as the Role name and click allow. The role is created and selected in the Existing Role field. See the screenshot "lambda_role"<br />
7. Leave everything default and click Next<br />
8. Click Create function<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc0cHkK1mwQ2u_lyS15HzR2VZn6vBVTOqNO_vqUe1woOkOa5-8rRJh09nZ6yGQSsojyd4WntIQ7MWCNmhN37jAosRMf7tAMkh2x1J_iq72_iFvPyHvs8dmNMSNYwHE4A1oNdeNOJlM7_E/s1600/Screen+Shot+2016-12-02+at+16.30.52.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="524" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc0cHkK1mwQ2u_lyS15HzR2VZn6vBVTOqNO_vqUe1woOkOa5-8rRJh09nZ6yGQSsojyd4WntIQ7MWCNmhN37jAosRMf7tAMkh2x1J_iq72_iFvPyHvs8dmNMSNYwHE4A1oNdeNOJlM7_E/s640/Screen+Shot+2016-12-02+at+16.30.52.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">lambda_role</td></tr>
</tbody></table>
<br />
<br />
<i>Testing the function in de AWS console</i><br />
<i><br /></i>
After the function is created we are going to test is using the AWS console.<br />
1. Click Test<br />
2. A dialog opens where you can specify the data sent to the Lambda function. Use the following testdata:<br />
<br />
{<br />
"deviceId": "deviceId",<br />
"lat": 52.5,<br />
"lng": 5.5<br />
}<br />
<br />
3. You can modify the testdata at any time by clicking Actions -> configure test event<br />
4. When done, click Test<br />
5. If everything went according to plan you should get an error message which states the following: Status Code: 400; Error Code: AccessDeniedException<br />
6. This is correct until this point. Although we created a custom role, we did not gave this role permissions to access our DynamoDB table.<br />
<br />
<i>Add DynamoDB permissions to our role</i><br />
<br />
1. Open the AWS console and navigate to the IAM section.<br />
2. Click on Roles<br />
3. Click on the lambda_location_persister to open it.<br />
4. Click Attach Policy<br />
5. In the filter field search for DynamoDB<br />
6. Select the AmazonDynamoDBFullAccess policy and click Attach<br />
7. Navigate back to AWS Lambda and test the function again. The function should be succesfull.<br />
8. Navigate to DynamoDB and select the DeviceLocation table and click on items. You should see one item added to the table.<br />
9 If you get a Status Code: 400; Error Code: ResourceNotFoundException error, check the region you specified in the Lambda implementation corresponds to the region of the DynamoDB table.<br />
<br />
Creating the API Gateway<br />
The API Gateway is used to create an HTTP endpoint which is the trigger for the Lambda function. Applications can communicate with this endpoint over HTTP.<br />
<br />
1. Open de AWS console and navigate to API Gateway.<br />
2. Create a new API. As the name use: LocationPersisterApi<br />
3. Click Create API<br />
4. Select Actions -> and click Create Resource, see screenshot_create_resource<br />
5. As resource name use: devicelocation, and click Create Resource<br />
6. Select Actions -> and click Create Method and select POST.<br />
7. In the method details select as Integration Type: Lambda Function, Lambda Region (the region you created the Lambda Function in, and as Lambda Function: persistDeviceLocation (the name of the Lambda function))<br />
8. Click Save and then OK<br />
9. Click Test and paste a test message in the body. This can be the same message as used in the Test section of the Lambda function. After the body is filled-in, click Test. If everything is OK you should see a HTTP 200 status code.<br />
10. Select Actions -> Deploy API and select [New Stage]. Specify prod as the stage name.<br />
11. Click Deploy. Your API will be deployed so that it can be accessed from the outside world.<br />
12. Navigate to the prod stage, expand the resources and select the POST method. Copy the URL after the 'Invoke URL' text in, for example, Postman. Execute an HTTP post with a test-message body. You should see a HTTP 200 status code (success).<br />
13. If you now open the DynamoDB tables and list the items you should see several items added to the table.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3VZ-YP5OvySNRmIw4Gi8qMzntZmh9fg1TzqVFjRCLOAEhO2HWxzD-_TQECpGqlsut95BOTmMO26H5afsWy2m5h3VEiITttWSMJ5E5VySzcgrJ-K4qtr03o-EoV_69fDtBi-5ZlnBVv48/s1600/resource.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="328" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3VZ-YP5OvySNRmIw4Gi8qMzntZmh9fg1TzqVFjRCLOAEhO2HWxzD-_TQECpGqlsut95BOTmMO26H5afsWy2m5h3VEiITttWSMJ5E5VySzcgrJ-K4qtr03o-EoV_69fDtBi-5ZlnBVv48/s640/resource.png" width="640" /></a></div>
<br />
<h2>
Conclusion</h2>
AWS Lambda, DynamoDB and API Gateway is a powerful to provision functionality in the cloud without having to provision entire servers or more full-fledged managed services like elastic beanstalk. This post showed you how to use those AWS services to create A Lambda function which uses DynamoDB and make it available using API gateway.<br />
<h2>
Resources</h2>
- The full source code of the example project can be found on <a href="https://github.com/jcraane/LambdaDynamoDBApiGateway">Github</a>.<br />
- <a href="https://aws.amazon.com/lambda/?sc_channel=PS&sc_campaign=acquisition_NL&sc_publisher=google&sc_medium=lambda_b&sc_content=lambda_e&sc_detail=aws%20lambda&sc_category=lambda&sc_segment=161199399068&sc_matchtype=e&sc_country=NL&s_kwcid=AL!4422!3!161199399068!e!!g!!aws%20lambda&ef_id=WEG2OAAABSUk6p@B:20161202175816:s">AWS Lambda</a><br />
- <a href="https://aws.amazon.com/dynamodb/?sc_channel=PS&sc_campaign=acquisition_NL&sc_publisher=google&sc_medium=dynamodb_hv_b&sc_content=dynamodb_e&sc_detail=aws%20dynamodb&sc_category=dynamodb_hv&sc_segment=144713450790&sc_matchtype=e&sc_country=NL&s_kwcid=AL!4422!3!144713450790!e!!g!!aws%20dynamodb&ef_id=WEG2OAAABSUk6p@B:20161202175843:s">AWS DynamoDB</a><br />
- <a href="https://aws.amazon.com/api-gateway/?sc_channel=PS&sc_campaign=acquisition_NL&sc_publisher=google&sc_medium=api_gateway_b&sc_content=api_gateway_e&sc_detail=aws%20api%20gateway&sc_category=api_gateway&sc_segment=161201038208&sc_matchtype=e&sc_country=NL&s_kwcid=AL!4422!3!161201038208!e!!g!!aws%20api%20gateway&ef_id=WEG2OAAABSUk6p@B:20161202175906:s">AWS Api Gateway</a><br />
<br />jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com15tag:blogger.com,1999:blog-117760846317593301.post-69147258962119649552016-08-21T19:29:00.003+02:002016-08-21T19:29:47.147+02:00IntelliJ TooltipRunner pluginLive coding during presentations can be a powerful mechanism to captivate an audience and this is preferably done using a tool which is suited for this. This means an IDE which provides some sort of presentation mode to focus on the code at hand.<br />
<br />
When watching <a href="https://www.youtube.com/watch?v=1OpAgZvYXLQ">Get a Taste of Lambdas and Get Addicted to Streams by Venkat Subramaniam</a> Venkat uses this technique of live coding. What is especially useful is the that TextMate is setup so that the results of program execution are displayed as a tooltip.<br />
<br />
Since I use IntelliJ instead of textMate I searched if there was something similar. Unfortunately there was not. There is the convenient presentation mode but not an option (that I can think of) to display the results of a Java main execution in a tooltip.<br />
<br />
That is why I created a plugin which does the same for IntelliJ. The plugin can be found <a href="https://plugins.jetbrains.com/plugin/8543?pr=idea">here</a> or you can install it using the Plugin manager in the Preferences. You can find a demonstration of the plugin <a href="https://youtu.be/Q5_8lpcdOjo">on YouTube</a>.<br />
<br />
The source code of this plugin can be found on Github: <a href="https://github.com/jcraane/intellij-tooltip-runner">https://github.com/jcraane/intellij-tooltip-runner</a>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-82451122868522528582016-02-22T06:56:00.004+01:002016-03-30T08:21:20.514+02:00Increase max open files in Elastic Search (OSX)<div style="line-height: normal; min-height: 13px;">
<div style="font-family: helvetica;">
Elastic Search, Logstash and Kibana (ELK) is an end-to-end stack which provides realtime analytics for almost any type of structured or unstructured data. </div>
<div style="font-family: helvetica;">
<br /></div>
<div style="font-family: helvetica;">
When importing large amounts of data using Logstash to Elastic Search (ES), the chances are that ES hit the limits of the maximum files it can open. This limit is seen as an error in the ES logs with the following description: (Too many open files)</div>
<div style="font-family: helvetica;">
<br /></div>
<div style="font-family: helvetica;">
To deal with this you can increase the maximum files ES (or any process) may open using the following steps:</div>
<div style="font-family: helvetica;">
<br /></div>
<span style="font-family: "helvetica";">1. First start ES with the following option: </span><span style="font-family: "courier new" , "courier" , monospace;">./elasticsearch -Des.max-open-files</span><span style="font-family: "helvetica";">. This wil show the maximum number of files ES is allowed to open, for example:</span><span style="font-family: "courier new" , "courier" , monospace;"> </span><span style="font-family: "courier new" , "courier" , monospace;">[2016-02-22 06:44:09,558][INFO ][bootstrap ] max_open_files [10240]</span><br />
<div style="font-family: helvetica;">
2. Now execute the following commands to increase the maximum number of files a process may open:</div>
<div style="font-family: helvetica;">
<br /></div>
<span style="font-family: "courier new" , "courier" , monospace;">- sudo sysctl -w kern.maxfiles=32000 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">- sudo sysctl -w kern.maxfilesperproc=32000</span><br />
<div style="font-family: helvetica;">
<br /></div>
<div style="font-family: helvetica;">
3. Execute the following commands to set the file limit for the terminal process (this is the terminal window to launch ES in)</div>
<div style="font-family: helvetica;">
<br /></div>
<span style="font-family: "courier new" , "courier" , monospace;">- ulimit -Sn 32000</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">- ulimit -Hn 32000</span><br />
<div style="font-family: helvetica;">
<br /></div>
<div style="font-family: helvetica;">
<b>For ES 1.7:</b></div>
<span style="font-family: "helvetica";">Start Elastic Search with the following command: </span><span style="font-family: "courier new" , "courier" , monospace;">./elasticsearch -Des.max-open-files -XX:-MaxFDLimit=true</span><br />
<div style="font-family: helvetica;">
<br /></div>
<div style="font-family: helvetica;">
<b>For ES 2.2</b></div>
<div style="font-family: helvetica;">
Execute the following commands:</div>
<div style="font-family: helvetica;">
<br /></div>
<span style="font-family: "courier new" , "courier" , monospace;">export ES_JAVA_OPTS=-XX:-MaxFDLimit</span><span style="font-family: "helvetica";"> (this increases the maximum files the JVM is allowed to open by default, see <a href="https://developer.apple.com/library/mac/documentation/Java/Reference/Java_VMOptionsRef/Articles/JavaVirtualMachineOptions.html">JVM configuration</a> for more information)</span><br />
<div style="font-family: helvetica;">
<br /></div>
<div style="font-family: helvetica;">
and then start ES with the following command: </div>
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">./elasticsearch -Des.max-open-files</span><span style="font-family: "helvetica";"> </span></span><span style="font-family: "helvetica";">(max_open_files should be 32000 now)</span><br />
<div style="font-family: helvetica;">
<div style="font-family: helvetica; font-size: 11px;">
<br /></div>
<div style="font-family: helvetica;">
<b><br /></b></div>
<div style="font-family: helvetica;">
<b>Heap sizes</b></div>
<div style="font-family: helvetica;">
<i><br /></i></div>
<div style="font-family: helvetica;">
You may also need to increase the heap size of both Logstash and Elastic Search. </div>
<div style="font-family: helvetica;">
<br /></div>
<span style="font-family: "helvetica";">To increase the heap of LogStash execute the following command before launching Logstash: </span><span style="font-family: "courier new" , "courier" , monospace;">export LS_HEAP_SIZE=2g</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">To increase the heap of Elastic Search execute the following command before launching ES: </span><span style="font-family: "courier new" , "courier" , monospace;">export ES_HEAP_SIZE=8g</span><br />
<div style="font-family: helvetica;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">When importing large files using Logstash, it may benefit to increase the number of workers to speed up the importing process. The default is 1. See the following example of the elasticsearch output plugin in Logstash:</span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">elasticsearch {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> action => "index"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> hosts => ["localhost"]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> index => "logstash-%{+YYYY.MM.dd}"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> workers => 4</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> flush_size => 1000</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span></div>
</div>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-24549953772276309622015-02-01T20:08:00.000+01:002015-02-01T20:08:31.233+01:00Android studio VS IntelliJ<b>Introduction</b><br />
<br />
On May 16, 2013 at Google I/O, Google announced Android Studio to be the primary IDE for building Android apps which is build on the IntelliJ platform. Since both the community and ultimate edition of IntelliJ also support Android development, what is the difference between the two and how to choose? In this post I will focus on Android studio and the ultimate edition of IntelliJ, which requires a paid subscription.<br />
<br />
I only focus on Android development. If you develop applications with a variety of different technologies, IntelliJ Ultimate edition is probably the best choice.<br />
<br />
<b>Added advantage</b><br />
<b><br /></b>
Let's make one thing clear: Android studio is an awesome IDE and for most of us it satisfies our Android development needs. But there are some features in IntelliJ which are lacking in Android studio which may come in handy when doing Android development. I will discuss those features below.<br />
<br />
<u>JSON support</u><br />
<u><br /></u>
IntelliJ Ultimate has full featured JSON support. If your Android application connects to a JSON endpoint, it may be worthwhile to have an editor with JSON support.<br />
<br />
<u>REST Client</u><br />
<u><br /></u>
IntelliJ Ultimate provides a REST client which can be used to execute URL requests to test available backend services.<br />
<br />
<u>Structural search and replace</u><br />
<u><br /></u>
<a href="https://www.jetbrains.com/idea/documentation/ssr.html">Structural search and replace</a> provides an advanced search & replace mechanism with knowledge about the source code. For example, I used this tool to rewrite the Google analytics V2 to Google analytics V4 in less then 10 minutes. Analytics code was scattered all over the place but structural search and replace lets you easily refactor such code.<br />
<br />
<u>Database support</u><br />
<u><br /></u>
If your application uses a relational SQLite database, a database editor is very helpful. IntelliJ Ultimate provides database support and also includes a connector to connect to an Android SQLite database which is really helpful to inspect the database of your application.<br />
<br />
<u>Advanced debugger</u><br />
<u><br /></u>
IntelliJ 14 provides an <a href="https://www.jetbrains.com/idea/whatsnew/#debugger_tab">advanced debugger</a> which shows variable values in the editor right next to their usages.<br />
<br />
<u>Analyze dependency matrix</u><br />
<u><br /></u>
The <a href="https://www.jetbrains.com/idea/features/dependency_analysis.html">Analyze dependency matrix</a> can be used to analyze the dependencies between projects and classes.<br />
<br />
<b>Conclusion</b><br />
<b><br /></b>
Although Android studio is a wonderful editor for Android development this post showed a couple of features in the IntelliJ Ultimate edition which may be worth the price when doing Android development.jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-85525376017238719502014-12-27T20:54:00.000+01:002014-12-27T20:57:45.378+01:00Parse.com anonymous and registered users (Android)<b>Introduction</b><br />
<b><br /></b>
When writing a mobile application you mostly always need a way to store the information outside of the application itself so the data is accessible to not only the application itself on a specific device, but on every device the application is installed on and perhaps even web applications. This means the application will need some sort of a backend service/API to communicate with. This usually also means the application will use some sort of account/user management.<br />
<br />
There are several so-called mobile backend as a service platform which facilitate this. The word mobile is a bit misplaced I think because the clients of those platforms are not always mobile devices. I therefor call those platforms Backend As a Service (BAAS). Parse.com is one of those platforms.<br />
<br />
This post talks about the way you can manage users with Parse.com and specifically how to use anonymous users and convert between an anonymous and registered user.<br />
<br />
<b>Anonymous user</b><br />
<b><br /></b>
A lot of apps require the user to register (create a user account) or login with a Facebook or similar account. If this is a required process, chances are that a certain group of users will not use your app because of the required login. If your app functionality allows, a possible work-around for this is to provide the app with anonymous user login. By using an anonymous user, the user of your app can experience all or most of the functionality of the app without requiring a user account. If the user likes your app, he/she can then sign-up for a registered account. Ideally, all of the data gathered during anonymous access, should be transferred to the registered account. Fortunately, the above functionality is fairly easy to implement using the Parse.com platform.<br />
<br />
<b>Enabling anonymous access</b><br />
<b><br /></b>
To enable your Parse.com app for using anonymous access, you have to do the following:<br />
<br />
1. Enable anonymous access in the Parse.com console. Go to Settings -> Authentication and enable "Allow anonymous access".<br />
<br />
2. Add the following code in the onCreate method of your Android Application class:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "APPLICATION_ID", "CLIENT_KEY");
ParseUser.enableAutomaticUser();
}
</code></pre>
<br />
By enabling automatic user, the call to ParseUser.getCurrentUser() always returns a user and thus is never null. You can check if the user is an anonymous user or a registered one by using the following code:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>ParseAnonymousUtils.isLinked(ParseUser.getCurrentUser());
</code></pre>
<br />
This can be useful to check if the sign-up button should be displayed or disabling some functionality which is only accessible to registered users.<br />
<br />
<b>Converting an anonymous user into a registered one</b><br />
<b><br /></b>
An anonymous user can be converted to a registered one. The data belonging to the anonymous user is also present on the registered one.<br />
<br />
Before converting an anonymous user, there are some things to consider:<br />
<br />
<ol>
<li>The username can not be left blank. You must explicitly specify a username and password on the user which is to be converted into a registered one.</li>
<li>It is adviced to save the anonymous user to the backend as soon as it is created. If this is not done and a call to saveInBackground is called on the registered user (after converting it from an anonymous one) a stack overflow is generated from the Android parse SDK. See also the following question on Stack-overflow (created by me): <a href="http://stackoverflow.com/questions/27595057/converting-an-anonymous-user-to-a-regular-user-and-saving">http://stackoverflow.com/questions/27595057/converting-an-anonymous-user-to-a-regular-user-and-saving</a></li>
</ol>
<div>
To save the user immediately after it is created, modify the Application code so that it looks like this:</div>
<div>
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>@Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, "APPLICATION_ID", "CLIENT_KEY");
ParseUser.enableAutomaticUser();
ParseUser.getCurrentUser.saveInBackground();
}
</code></pre>
<br />
The anonymous user can now be converted into a registered one with the following code:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>findViewById(R.id.createUser).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final String accountUsername = username.getText().toString();
final String accountPassword = password.getText().toString();
final ParseUser user = ParseUser.getCurrentUser();
user.setUsername(accountUsername);
user.setPassword(accountPassword);
user.signUpInBackground(new SignUpCallback() {
@Override
public void done(final ParseException e) {
if (e != null) {
Toast.makeText(MainActivity.this, "Signup Fail", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Signup fail", e);
} else {
Toast.makeText(MainActivity.this, "Signup success", Toast.LENGTH_SHORT).show();
final ParseUser user = ParseUser.getCurrentUser();
user.put("phone_no", "31612345678");
user.saveInBackground(new SaveCallback() {
@Override
public void done(final ParseException e) {
if (e != null) {
Toast.makeText(MainActivity.this, "Save data Fail", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Signup fail", e);
} else {
Toast.makeText(MainActivity.this, "Save data success", Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
}
})
</code></pre>
<br />
Please note that the data associated with the user in the saveInBackground call (after sign-up is successful) could also be associated immediately to the user before the signUp call. This saves an extra network call. The call to saveInBackground is pure for demonstration purposes.<br />
<br />
<b>Conclusion</b><br />
<b><br /></b>
This post showed the benefits of an anonymous user of a mobile app and how the anonymous user can be used with the Parse.com platform. It also showed code examples of how an anonymous user is converted into a registered one and the potential problems and solutions with it.<br />
<br /></div>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com1tag:blogger.com,1999:blog-117760846317593301.post-23591922347768795102014-02-08T20:40:00.000+01:002014-02-08T20:41:44.840+01:00IntelliJ: the power of structural search and replaceSometimes you run into a situation where you want to refactor some code but cannot use the regular refactorings. For example, take the following code:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>jQuery("body").on("change", "#fontSelector", "change", function () {
var selectedFont = jQuery("#fontSelector").val();
layoutDesigner.selectFont(selectedFont);
});
</code></pre>
<br />
I wanted to replace the above code with the following:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>jQuery("#fontSelector").off("change");
jQuery("#fontSelector").on("change", function () {
var selectedFont = jQuery("#fontSelector").val();
layoutDesigner.selectFont(selectedFont);
});
</code></pre>
<br />
Sure, I could rewrite this manually. But this takes a long time with dozens of such event handling constructs, all with different selectors, events and functions. Structural search and replace to the rescue.<br />
<br />
But instead of writing how you could do this with structural search and replace, I recorded a little screencast which demonstrates the concept. The video can be found here: <a href="https://www.youtube.com/watch?v=Jb-YNgDClKg">https://www.youtube.com/watch?v=Jb-YNgDClKg</a>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-79545775037229382992014-01-28T20:34:00.001+01:002014-01-28T20:38:16.520+01:00Android: location based services<h3>
Introduction</h3>
<div>
Developing applications for mobile devices gives us a lot more opportunities for context based information than a traditional web application. One of the inputs for context sensitive information is the users current location. This post describes several ways an Android application can obtain the users current location.</div>
<h3>
Location API's</h3>
<div>
In previous versions of the Android SDK you had to manually implement a location service which abstracts away the underlying location providers (GPS or cellular based). This was not ideal since as a developer of an application, you probably are not concerned about the implementation details of obtaining a users location.</div>
<div>
<br /></div>
<div>
Fortunately Google's Location API's provide a much better way for working with location data. The Location API's provide the following functionality:</div>
<div>
<ul>
<li>Fused location provider which abstracts away the underlying location providers.</li>
<li><span style="font-family: Times, Times New Roman, serif;">Geofencing</span><span style="font-family: Arial, Helvetica, sans-serif;">.</span><span style="background-color: white; font-family: Times, Times New Roman, serif;"> <span style="line-height: 19px;">Lets your application setup geographic boundaries around specific locations and then receive notifications when the user enters or leaves those areas.</span></span></li>
<li>Activity recognition. Is the user walking or in a car.</li>
</ul>
</div>
<h3>
Check for Google play services</h3>
<div>
Working with the Location API's require the presence of the Google Play Services application on the device. It is good practice to test for the presence of Google play services before using the API. This can be done with the following code:<br />
<br /></div>
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>protected boolean testPlayServices() {
int checkGooglePlayServices = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity());
if (checkGooglePlayServices != ConnectionResult.SUCCESS) {
// google play services is missing!!!!
/*
* Returns status code indicating whether there was an error.
* Can be one of following in ConnectionResult: SUCCESS, SERVICE_MISSING,
* SERVICE_VERSION_UPDATE_REQUIRED, SERVICE_DISABLED, SERVICE_INVALID.
*/
GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, getActivity(), 1122).show();
return false;
}
return true;
}
</code></pre>
<b>Code listing 1</b><br />
<b><br /></b>
Code listing 1 shows how to check for the presence of Google play services. If the Google play services are not present a dialog is displayed giving the user the opportunity to download and install the Google play services application. This method returns false if the services are not found and can be placed around any code requiring Play services.<br />
<div>
<br /></div>
<div>
<b>Obtaining the users location</b></div>
<div>
<br />
The primary class for using the Location API's is the LocationClient. The first thing to do is instantiating the LocationClient and passing the required listeners. See the following code which is usually called from the onCreate from within an activity or onActivityCreated if the LocationClient is instantiated within a fragment.<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>locationClient = new LocationClient(getActivity(), this, this);
</code></pre>
<br /></div>
<div>
The parameters are:<br />
<br />
<ol>
<li>The Context</li>
<li><a href="http://developer.android.com/reference/com/google/android/gms/common/GooglePlayServicesClient.ConnectionCallbacks.html">ConnectionCallbacks</a>. Defines the onConnected() and onDisconnected() methods.</li>
<li><a href="http://developer.android.com/reference/com/google/android/gms/common/GooglePlayServicesClient.OnConnectionFailedListener.html">OnConnectionFailedListener</a>. Defines the onConnectionFailed() method.</li>
</ol>
</div>
When the LocationClient is instantiated, the next thing to do is calling the connect() method of the LocationClient. This is typically done in the onResume method. In the inPause method the disconnect() method is called of the LocationClient. This ensures the LocationClient is only active when the activity is running. Should you need constant tracking of the users location when the app is in the background, it is better to create a background service for this.<br />
<br />
When the connect() method is successful, the onConnected() callback is called. In this method you can obtain the users last known location using the following method:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>locationClient.getLasLocation();
</code></pre>
<br />
<b>Periodic location updates</b><br />
<br />
Registering for periodic location updates involves slightly more work. The first thing to do is creating a new LocationRequest object. This object specifies the quality of service for receiving location updates. The following code demonstrates this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>private static LocationRequest createLocationRequest() {
final LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// The rate at which the application actively requests location updates.
locationRequest.setInterval(60 * MILLISECONDS_IN_SECOND);
// The fastest rate at which the application receives location updates, for example when another
// application has requested a location update, this application also receives that event.
locationRequest.setFastestInterval(10 * MILLISECONDS_IN_SECOND);
return locationRequest;
}
</code></pre>
<br />
After the LocationRequest is created and the connect() method of the LocationClient is successful, the onConnected method is called. In this method the LocationClient is instructed to send periodic location updates to the application using the following code:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>locationClient.requestLocationUpdates(locationRequest, this);
</code></pre>
<br />
The parameters are:<br />
<br />
<ul>
<li>locationRequest. Specifies the quality of services of the location updates.</li>
<li><a href="http://developer.android.com/reference/android/location/LocationListener.html">LocationListener.</a> Defines several callback methods including the onLocationChanged which is called when a new location is available.</li>
</ul>
<b>Required dependencies</b><br />
<b><br /></b>
To use the Google play services in your application you have to define the correct dependencies in the build.gradle. There are two versions of the API: one for Android 2.3. and higher and one for Android 2.2.<br />
<br />
Use the SDK manager to install the required packages. For Android 2.3 these are:<br />
<br />
<ul>
<li>Google play services</li>
<li>Google repository</li>
</ul>
<div>
For Android 2.2 these are:</div>
<div>
<ul>
<li>Google play services for Froyo</li>
<li>Google repository</li>
</ul>
</div>
<br />
So if your applications targets Android 2.2 you must use the Google play services for Froyo library. In your build.gradle specify the following dependency:<br />
<br />
For Android 2.3:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>dependencies {
compile 'com.google.android.gms:play-services:4.0.30'
}
</code></pre>
<br />
For Android 2.2:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>dependencies {
compile 'com.google.android.gms:play-services:3.2.65'
}
</code></pre>
<br />
<b>Testing with mock locations</b><br />
<b><br /></b>
To test with mock locations you have to do the following:<br />
<br />
<br />
<ol>
<li>Enable mock locations in the developer options.</li>
<li>Download the sample LocationProvider example app: <a href="http://developer.android.com/training/location/location-testing.html">http://developer.android.com/training/location/location-testing.html</a></li>
<li>Modify the LocationUtils class with an array of locations you want to test with.</li>
<li>Install the LocationProvider sample app on your device.</li>
<li>Start the LocationProvider sample app.</li>
<li>Start the application you want to test the location functionality for.</li>
</ol>
<br />
A handy website to get the latitude and longitude of an address for testing purposes is: <a href="http://www.itouchmap.com/latlong.html">http://www.itouchmap.com/latlong.html</a><br />
<br />
<h3>
Conclusion</h3>
<div>
Working with location data in your mobile application can add a new dimension to the user experience. This article explains the steps needed to use the Google Location API's for obtaining the users current location.</div>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-17893091614557639512013-09-20T16:37:00.003+02:002013-09-20T16:41:19.504+02:00MyBatis: mapping a mapAs some of you will know I am a huge fan of MyBatis. I have used it in a lot of projects and it never failed me. I like how you are in control of the SQL and the flexibility this brings by mapping result sets to classes instead of mapping tables to classes.<br />
<br />
Recently I wanted to map some columns from a table to actual typed properties of an object, and some columns to a <string object="">property of type Map within that same object. Consider the following class:</string><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public class Person {
private String firstName;
private String lastName;
private Map<string object=""> dynamicProperties;
// Getters and setters omitted.
}
</string></code></pre>
<br />
and the following query:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>select firstname, lastname, pref_1, pref_2, pref_3 from person;
</code></pre>
<br />
The following resultmap maps the result of the query to the Person class:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><resultMap id="personDynamicProperties" type="map">
<result column="pref_1" property="pref_1"/>
<result column="pref_2" property="pref_2"/>
<result column="pref_3" property="pref_3"/>
</resultMap>
<resultMap id="personResult" type="Person">
<result column="firstname" property="firstName"/>
<result column="lastname" property="lastName"/>
<association property="dynamicProperties" resultMap="personDynamicProperties"/>
</resultMap>
</code></pre>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-65613008611847707722013-07-12T23:46:00.003+02:002013-07-12T23:46:25.590+02:00Java 7 try-with-resourcesJava 7 provides better resource management for resources that need to be closed when finished working with, for example files, streams, database connection and sockets. This language construct is called the try-with-resources statement. The mechanism that makes this work is called the AutoCloseable interface. The Java 7 resource classes all implement this interface. The signature of this interface looks like this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public interface AutoCloseable {
void close() throws Exception;
}
</code></pre>
<br />
It declares one method, close(), which is automatically invoked on objects managed by the try-with-resources statement.<br />
<br />
Although Java 7 resource classes implement this interface, a lot of time the libraries you use do not because the library is not updated to use the AutoCloseable interface or the project cannot simply update to a newer version.<br />
<br />
Most of the time this is easy to solve. Just subclass the resource that should be able to participate in the try-with-resources statement. Take the ITextRenderer (form the Flying Saucer project) as an example. When finished working with the ITextRenderer, the finishPDF() method should be called. Normally you would do that in a finally block. By creating a new class extending from ITextRenderer and implementing the AutoCloseable interface this class can participate in automatic resource management. The AutoCloseableITextRenderer looks like this:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public class AutoCloseableITextRenderer extends ITextRenderer implements AutoCloseable {
@Override
public void close() {
super.finishPDF();
}
}
</code></pre>
<br />
Extending the original class makes the most sense since the subclass <b>is</b> an ITextRenderer. You would use composition if the class cannot be extended because it is final.<br />
<br />
And this is how you would use it:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>try (final AutoCloseableITextRenderer iTextRenderer = new AutoCloseableITextRenderer()) {
ByteArrayOutputStream out; // contains the data to be converted to PDF, not shown here.
iTextRenderer.setDocumentFromString(new String(out.toByteArray()));
iTextRenderer.layout();
iTextRenderer.createPDF(pdfOutputStream);
pdfOutputStream.flush();
}
</code></pre>
<br />
Thats all. Please note that I did not throw an exception from the close() method in the AutoCloseableITextRenderer. The Javadoc of the AutoCloseable interface says the following about this:<br />
<blockquote class="tr_bq">
While this interface method is declared to throw {@code Exception}, implementers are strongly encouraged to declare concrete implementations of the {@code close} method to throw more specific exceptions, or to throw no exception at all if the close operation cannot fail.</blockquote>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-72643983228242871252013-06-20T14:26:00.000+02:002013-06-20T14:26:40.791+02:00Height problem when rendering an ExtJs 4 application in a custom divThis post is verified with Ext Js version 4.<br />
<br />
ExtJs applications can be run in the whole browser window or in a small part of a larger application, for example in a div. You may want to render an ExtJs application in a div if you have a common HTML structure with navigation capabilities outside the ExtJs application. To render an ExtJs application to a div do the following:<br />
<br />
<ul>
<li>create an HTML which contains the div where the application is rendered</li>
<li>Create an app.js file which is the actual ExtJs application. </li>
</ul>
Below is an example of an index.html with a div named appContent where the ExtJs application is rendered to:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Sample app</title>
<script type="text/javascript" src="extjs/ext-debug.js"></script>
<script type="text/javascript" src="extjs/ext-theme-neptune.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div id="appContent" class="app-content">
</div>
</body>
</html>
</code></pre>
<br />
And here is an example of app.js which renders the application to a div:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>Ext.application({
name: "SampleApp",
launch: function () {
Ext.create("Ext.panel.Panel", {
renderTo: Ext.getElementById("appContent"),
autoCreateViewPort: false,
layout: {
type: "hbox",
align: "stretch"
},
id: "appContainer",
listeners: {
beforerender: function () {
Ext.getCmp("appContainer").setHeight(Ext.get("appContent").getHeight());
Ext.getCmp("appContainer").doLayout();
Ext.EventManager.onWindowResize(function () {
Ext.getCmp("appContainer").setHeight(Ext.get("appContent").getHeight());
Ext.getCmp("appContainer").doLayout();
});
}
},
items: [
{
xtype: "label",
text: "Sample App",
flex: 1
}
]
});
}
});
</code></pre>
<br />
Please notice the listeners section. What I noticed was that with some layouts (for example the hbox, vbox and borderlayout) the application did not occupy the whole size of the div. When I rendered the same application using a viewport the application size was a large as the browser window.<br />
<br />
The beforerender listener fixes this issue. It basically sets the height of the application container to the height of the div and calls doLayout to update the view. This same logic is also added to the onWindowResize event to adjust the size of the application when the browser window is resized. This fixed the problem for me.jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-29105239993066172452013-03-23T15:13:00.002+01:002013-03-23T15:13:34.888+01:00How to: web service mock with SoapUI<h2>
Introduction</h2>
A lot of organizations use web services (WSDL) for system integration. Often those services are developed alongside the application that uses those services. Instead of waiting for those services to be developed, the application which consumes the web service can develop a mock implementation of the service to test against.<br />
<br />
<h2>
Several strategies</h2>
There are several strategies for developing mock services from a WSDL. One of these strategies is using <a href="http://www.soapui.org/">SoapUI</a>. SoapUI is able to consume the WSDL and generate a mock service from it. After the mock service is created, the application in question can consume this mock service and start using it.<br />
<br />
The advantage of mocking this way, is that the application makes a full HTTP network round-trip when calling the respective service. All relevant components within the application (WSDL client, parsing the response message) are covered.<br />
<br />
Instead of describing how to mock a web service using SoapUI, I created a small screencast demonstrating this. The screencast can be found here: <a href="http://www.youtube.com/watch?v=fSZ8HmQqKpA">Web service mocks with SoapUI</a><br />
<br />
I think this screencast is more clear and easier to follow than written text. To be effective I keep my screencasts shorter than 5 minutes. Descriptive subtitles are also included. Please let me know if you like this format.<br />
<br />
<h2>
Final thoughts</h2>
Besides speeding up development, mocks/stubs may also be used to put the system in a known state which enables automatic integration testing.<br />
<br />
<br />
<br />jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com1tag:blogger.com,1999:blog-117760846317593301.post-62645686684273368302013-03-13T20:14:00.001+01:002013-03-13T20:14:35.072+01:00Reasons for IntelliJ<h2>
Introduction</h2>
<div>
I often get the question why I use Intellij in favor of another IDE, in this case Eclipse. Most of the time I answer that question by demonstrating some features of IntelliJ and showing how integrated everything is. This got me thinking about what are the actual reasons that I use it. This post will try to make that clear and help others decide if the switch is worth it or not.<br />
<br /></div>
<b>
Some background</b><br />
<b><br /></b>
<div>
<div>
I had been a long time Eclipse (7+ years) user before I made the jump to IntelliJ. Before Eclipse, I worked with Rational Application Developer, WSAD, JBuilder and Visual Age for Java. Compared to these IDE's, Eclipse was a joy to use. I could, for example, generate getters and setters, which was not possible in one of the older IDE's (we are talking about more than 10 years ago). Although I quite liked Eclipse I always thought there were some deficiencies. Mainly in the following areas:</div>
<div>
<ul>
<li>Why was there no core functionality bundled with the standalone Eclipse variant? For example Subversion and Maven integration.</li>
<li>Why was it always painful to setup an Eclipse version to your liking with all the required plugins? With every new version I spent always nearly half a day setting up my IDE. This is unacceptable I think. The more plugins and functionality the harder it got.</li>
<li>Updating to a new version was sometimes painful. Plugins that stopped working for example.</li>
<li>I never quite liked the concept of a workspace. I already organize my projects on disk so I do not need a workspace concept.</li>
<li>I did not like the idea of different perspectives. Why do I have to think about the context I am working in? For example: working with Java and Flex in one project. When I am in the Flex perspective my Java code completion/refactoring did work in Java files. Context should be file or even fragment driven.</li>
</ul>
</div>
<div>
Please note that the above are personal opinions and may vary between users. Despite of this I was quite productive in Eclipse and liked the performance of it. Also note that these observations are from a couple of versions back. Things may have changed.</div>
<div>
</div>
<div>
Around 2007/2008, a colleague of mine introduced me to Intellij, I think it was version 7 back then. My first reaction was I don't need another IDE. He showed me some features, like code inspections, and I said I would give it a try. My main obstacle back then was the price. That year I also gave a talk at the Dutch Java User group conference. Every speaker received a free IntelliJ license from JetBrains. I then decided I would give it a try. After the first two or three days I thought I would give up. I had to learn all new key-bindings and I was less productive. I persisted and after a week or so I begun seeing the benefits of it. After version 7 I upgraded to 8, 9 without any problem. Things could be different. At the moment I work with the latest version, 12.1 EAP. Below are some of my reasons why I do most (if not all) of my development work in IntelliJ.</div>
</div>
<div>
<br /></div>
<div>
<b>Major features</b><br />
<ul>
<li>It is an integrated solution. I do a lot of different development work with a lot of different technologies, for example: Java, HTML/CSS/JavaScript, Android, Grails/Groovy, Flex, Subversion, Git, Maven, Ant etc. This is all possible with IntelliJ out-of-the box. There is no need to install separate plugins, which saves me a huge amount of setup time. Just download and install it and you're good to go.</li>
<li>The editor itself. I invest heavily in knowing all the shortcuts. By knowing all the shortcuts I can code very fast. The instant code completion (not having to hit Ctlr-space all the time) is a joy to work with. Just type a couple of characters and hit Tab to complete the code. When I generate code, the cursor almost always is in the correct position to begin typing again. No need to touch the mouse or whatever.</li>
<li>Code inspections and analysis tooling build in. I find it important to keep my code clean and bug free. The build in inspections and the ability to auto solve them are a really nice addition. Besides this you also have a dependency matrix viewer to get a quick overview of the dependency structure of your application and a duplicate code checker.</li>
<li>Live templates. Live templates greatly increase coding speed. To make the most of it, I highly recommend creating your own templates. This is very easy. Just select a piece of code and select Save as Live template from the Tools menu. Press Ctrl/Cmd+J to view the live templates.</li>
<li>Maven/Gradle integration out of the box. Just import a Maven project and Intellij knows the modules, dependencies etc. You can easily generate a dependency diagram from the Maven pom file to view all the dependencies at a glance. See figure 1 for an example of the Maven dependency viewer.</li>
<li>Some handy tools. I often use the database editor and the RESTful web service test utility. The database editor has code completion in SQL and table creation. With the RESTful web service tester you can easily test HTTP services. The response can then me immediately saved and formatted as JSON or XML.</li>
<li>Powerful refactorings and structural search & replace. IntelliJ knows a lot about my code. For example in Android: when I rename an image in the values/hdpi folder, it also renames the corresponding images in the mdi and xhdpi folder but also updates my XML views and code references to that image.</li>
<li>Tasks and Contexts. I use IntelliJ in combination with YouTrack (there are more issue trackers that IntelliJ can integrate with). It is really easy to start working on an issue. IntelliJ creates a new context that tracks the files that belongs to that specific issue. I can mark the issue in progress and when I commit my changes it takes the comments from the context and uses this as the commit comments. It also changes the status of the issue to resolved when done working on the issue. All from within the IDE itself, no need for context switching.</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8swfavaWm47Vp023xPrYea9uxFJBLdZVuaQT8qNF348UeWyaycFihiL1VfeeQBN4IkdyuUxPHVOM5BjYBCMIhk5WdQQ3rOh_hBuRFdMJhlrwpB1-eucPGVUedPhpnTyYx25Pvfj5irfs/s1600/mavenDependencies.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="454" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8swfavaWm47Vp023xPrYea9uxFJBLdZVuaQT8qNF348UeWyaycFihiL1VfeeQBN4IkdyuUxPHVOM5BjYBCMIhk5WdQQ3rOh_hBuRFdMJhlrwpB1-eucPGVUedPhpnTyYx25Pvfj5irfs/s640/mavenDependencies.jpg" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1: Maven dependency viewer</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<b>Smaller features</b></div>
<div>
<b><br /></b></div>
<div>
<div>
And then there are the smaller but just as important features which increase my productivity:</div>
<div>
<ul>
<li>Stacked clipboard. You can have multiple entries in your clipboard. Just hit Ctrl-Shift-V to show the clipboard stack.</li>
<li>Column mode in the editor. This comes in handy when working with fixed structure files like CSV for example.</li>
<li>Darcula theme. This is one of the best dark themes I encountered. A dark theme is especially useful when coding in the evening with the lights dimmed. It is less stressful for the eyes I think. See figure 2 for an example of the Darcula theme.</li>
<li>Stack trace analyzer. Just copy a stack trace from the clipboard and IntelliJ analyses it and matches it with the code to easily navigate to the problem at hand.</li>
<li>Unit test and coverage integration.</li>
<li>And many more.</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM0TGywkBlSUVtTDF1rzcnbKtNJFGZZnxMzesxpgyhmL7zR59EfWHAOomL3jiRkfSQna_lJmhpcUw6d6p8TKnPfNcbkS9eUg8a4hUCZfgca9WzZqb97MGB4sLeElXF7HyihRxfSYIk96Y/s1600/IntelliJDarcula.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="404" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM0TGywkBlSUVtTDF1rzcnbKtNJFGZZnxMzesxpgyhmL7zR59EfWHAOomL3jiRkfSQna_lJmhpcUw6d6p8TKnPfNcbkS9eUg8a4hUCZfgca9WzZqb97MGB4sLeElXF7HyihRxfSYIk96Y/s640/IntelliJDarcula.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2: IntelliJ Darcula theme</td></tr>
</tbody></table>
<div>
<br /></div>
<h2>
Final thoughts</h2>
</div>
</div>
<div>
This article describes the reasons why I use IntelliJ as my primary development tool of choice. Please note that this is my personal opinion. Also, this is obviously not an exhausted list. I would like to hear from you why you choose IntelliJ.</div>
<div>
<br /></div>
<br /></div>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com5tag:blogger.com,1999:blog-117760846317593301.post-83384174835665316142013-02-11T16:43:00.000+01:002013-02-11T16:43:10.104+01:00Evaluating new frameworks, libraries and technologies<h2>
Introduction</h2>
New frameworks and libraries are developed so fast it is nearly impossible to evaluate all of them. This can make it hard to judge whether a particular technology is worth investing (time) in. This post gives you some tips which may help when evaluating new technology.<br />
<br />
<h2>
Conceptual level</h2>
Although there are many different libraries and frameworks, most of them can be grouped based on some conceptual differentiation. The following concepts may help to give an idea of this conceptual differentiation:<br />
<br />
<ul>
<li>Component based frameworks</li>
<li>Request/response based frameworks</li>
<li>Object Relational Mapping</li>
<li>Map-reduce</li>
<li>Key-value stores</li>
<li>Messaging</li>
<li>And many more... </li>
</ul>
<br />
When evaluating a specific technology it helps to identify to which concept or concepts it belongs. Before further analysis of a particular technology, make sure you understand the concepts. Without this understanding it is almost impossible to do an objective analysis. Understanding these concepts requires an investment in time. Usually in the form of reading, watching presentations, experimenting, training and talking to others. Understanding the concepts will make it easier to objectively evaluate a particular technology.<br />
<br />
<h2>
Simpler is usually better</h2>
<br />
One of the key actions in evaluating a particular technology is to determine if and how it satisfies the given requirements. A lot of frameworks and libraries provide a 1 minute introduction, a 5 minute guide, a 30 minute tutorial and more. I really like these sorts of introductions since it usually gets you up-to-speed quickly. Besides getting up-to-speed quickly, a more important factor is the complexity of the given solution. I really like the idea of "Make things as simple as possible, but not simpler".<br />
<br />
The starter guides, as mentioned above, present the readers with a relatively simple case or problem to demonstrate the key features of a given technology. To find out if a certain technology will fit I suggest to look at the complexity of the solution for the cases in the introduction guides.<br />
<br />
In my opinion, if the solution for a relatively simple case or problem is complex and not easy to understand, how can a solution to a more complex problem be easy to understand? This complexity comes of course in various flavours:<br />
<br />
<ul>
<li>How much code do I need to write to get even the simplest things done?</li>
<li>How many classes do I need to extend? </li>
<li>What and how much configuration should I write?</li>
<li>What is the quality of the documentation?</li>
<li>How can I easily test my solution?</li>
<li>Etc.</li>
</ul>
<br />
If the solution to a simple problem is indeed simple and easy to understand, it is worth investigating more time to find out if the technology satisfies your requirements. If the solution to a simple problem is not simple and not easy to understand, think long and hard before investing more time in it.<br />
<br />
<h2>
Conclusion</h2>
<br />
New frameworks and libraries are developed so fast it is nearly impossible to evaluate all of them. To speed up the decision process make sure you understand the technology at the conceptual level. Once you understand the conceptual level, experiment with the technology using introduction guides if they are available.<br />
<br />
If, from those introduction guides, solutions to a given problem are simple and easy to understand, it may be well worth spending more time investigating the particular technology for more complex problems. If not, proceed with care.<br />
<br />
As always, your mileage may vary.jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-80984024920467656742012-11-13T19:47:00.002+01:002012-11-14T07:21:49.808+01:00Sample generated melodiesBased on some questions, I uploaded a couple of sample melodies in MP3 format which are generated by my genetic algorithms melody generator. The generated sample melodies can be found here: <a href="http://code.google.com/p/melodycomposition/downloads/list">http://code.google.com/p/melodycomposition/downloads/list</a>.<br />
<br />
The original article of the melody generator can be found here: <a href="http://jcraane.blogspot.nl/2009/06/melody-composition-using-genetic.html">Melody generator</a>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-42438191988466231662012-10-18T21:31:00.002+02:002012-10-18T21:31:22.009+02:00Kinect within VMWareRecently Microsoft announces the availability of the<a href="http://www.microsoft.com/en-us/kinectforwindows/develop/developer-downloads.aspx"> Kinect 1.6 SDK</a>. One of the big enhancements in this release is the support for the Kinect device within a virtual machine (VMWare or Parallels)!<br />
<br />
For a client we developed a Kinect application which was shown at the Dutch Floriade festival. More details about this project in a next post.<br />
<br />
The problem with the old Kinect SDK was the inability to use the Kinect within a virtual machine. Because of this I had to create a bootcamp partition and install Windows on it just for the sole purpose of Kinect development. The 1.6 SDK solves this!<br />
<br />
Below are the results of my tests with the Kinect within VMWare.
I used the following system configuration to test on:<br />
<ol>
<li>MacBook pro 2011 with 2Ghz core i7 and 8GB RAM..</li>
<li>OSX Mountain Lion.</li>
<li>VMWare Fusion 5 running Windows 7.</li>
<li>Visual Studio Express 2012.</li>
<li>Kinect 1.6 SDK.</li>
</ol>
<div>
First I tested the above setup with the Xbox Kinect. This did not work which I more or less expected since Mircosoft wants to push the Kinect for Windows for Kinect development.</div>
<div>
<br /></div>
<div>
Next I tested was the Kinect for Windows. After I connected the device I started the Shape Game sample application. The device was found and worked immediately! I also tested the Kinect with our own application and this also worked as expected.</div>
<div>
<br /></div>
<div>
Ont thing I noticed was that both applications did not run as smooth as when I ran the application under bootcamp. After examing my virtual machine settings I noticed I had given it only 1 cpu core (out of the available 8). This could be the problem. When I changed the maximum number of cpu cores the virtual machine may use to 4, things ran much smoother. There was no noticeable difference when running within a virtual machine or bootcamp. </div>
<div>
<br /></div>
<div>
For more information about the 1.6 SDK see: <a href="http://msdn.microsoft.com/en-us/library/jj663803.aspx#SDK_1pt6_M2">http://msdn.microsoft.com/en-us/library/jj663803.aspx#SDK_1pt6_M2</a>.<br />
<br />
<b>Conclusion</b><br />
The new Kinect 1.6 SDK does work within a virtual machine if the Kinect for Windows is used.</div>
<div>
<br /></div>
<div>
<br /></div>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com16tag:blogger.com,1999:blog-117760846317593301.post-79803747153002466612012-10-04T12:57:00.000+02:002012-10-04T12:57:08.234+02:00IntelliJ SSR: replace constructorsSuppose you have a large codebase which uses a particular class named SomeClass (nice descriptive name :)). SomeClass has one constructor:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public SomeClass(String a, String b, String c, String d) {
// Do something
}
</code></pre>
<br />
This constructor is used at various places in the codebase.<br />
<br />
At some point in time an update to SomeClass is made which introduced another constructor:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public SomeClass(String a, String b) {
// Do something
}
</code></pre>
<br />
Lets assume you want all calls to the 4 argument constructor to be replaced by the 2 argument constructor. The arguments of the 4 argument constructor should be used in the 2 argument constructor in the following way: new SomeClass(1, 2, 3, 4) becomes new SomeClass(3, 1).<br />
<br />
See the following example:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
public class UsageOfSomeClass {
private SomeClass instance_1 = new SomeClass("a", "b", "c", "d");
private SomeClass instance_2 = new SomeClass("d", "e", "f", "g");
private SomeClass instance_3 = new SomeClass("h", "i", "j", "k");
public static void main(String[] args) {
SomeClass someClass = new SomeClass("1", "2", "3", "4");
}
}
</code></pre>
<br />
Should become:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public class UsageOfSomeClass {
private SomeClass instance_1 = new SomeClass("c", "a");
private SomeClass instance_2 = new SomeClass("f", "d");
private SomeClass instance_3 = new SomeClass("j", "h");
public static void main(String[] args) {
SomeClass someClass = new SomeClass("3", "1");
}
}
</code></pre>
<br />
You can achive the following for an entire codebase with one single structural search and replace action. Use the following templates to achieve this:<br />
<br />
Search template: new SomeClass($arg1$, $arg2$, $arg3$, $arg4$)<br />
Replace tempalte: new SomeClass($arg3$, $arg1$)<br />
<br />
Hit find and Replace All. Thats it!jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-9579097966427258382012-09-09T22:56:00.000+02:002012-09-09T22:56:55.366+02:00IntelliJ: HTML and structural search and replaceI was asked to do some quick fix on some website. The website used a lot of table structures for laying out the page. To give an impression, the page had more than 50 tables each with 4 columns and 20+ rows.<br />
<br />
There was no external CSS used. All styling of the tables was done with attributes or inline style elements. The styling was also not consistent throughout the page so each table looked slightly different.<br />
<br />
Here is an example:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><table>
<tr>
<td width="200px">Some text</td>
<td width="221px">More text</td>
<td width="300px" height="100px">Example</td>
<td style="width: 210px;">HelloWorld</td>
<td style="width: 190px;">More text</td>
<td id="test" style="width: 222px;"></td>
<td id="test2" class="right" style="width: 200px;">Java</td>
</tr>
</table>
</code></pre>
<br />
Without rewriting the whole site at once I wanted to remove all the inline styles so I could use css to style all the tables the same. That at least looked more attractive in the short run while in the long run we could focus on a complete redesign of the site.<br />
<br />
The first thing I wanted to do was replace all the td elements with inline styling with plain, empty td elements. As written in my previous posts, IntelliJ's structural search and replace features fits this use case nicely.<br />
<br />
In the structural search and replace dialog I used the following:<br />
<br />
<b>Search template: <br />
</b><br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><td $width$="$value$" $style$="$value$">$text$</td><b>
</b></code></pre>
<br />
<b>Replace template: </b><br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><td>$text$</td><b>
</b></code></pre>
<br />
In the Edit variables dialog I specified a minimum count of zero for the $width$, $style$ and $text$ variable. The $value$ variable has a minimum count of one. For all variables I used a maximum count of one.<br />
<br />
The template searches for all td elements with zero or one width or style attributes (or both) and with or without text. The replace template replaces the td found with the search template in a plain td. The output of the HTML after the search and replace is run is:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><table>
<tr>
<td>Some text</td>
<td>More text</td>
<td>Example</td>
<td>HelloWorld</td>
<td>More text</td>
<td></td>
<td>Java</td>
</tr>
</table><b>
</b></code></pre>
<br />
After this replacement I could just insert the appropriate CSS and style all tables consistently. Without structural search and replace I think such scenario's take considerably longer to execute.<br />
<div>
<br /></div>
<div>
Hope you enjoyed it.</div>
<div>
<br /></div>
<div>
If you have other interesting structural search and replace use cases please share them.</div>
jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-69265536449981893072012-08-11T22:28:00.002+02:002012-08-12T11:11:41.812+02:00IntelliJ: customize the editorIn this post I explain the modifications I make in the configuration of the IntelliJ editor and project window. With these modifications I find it even more easier to work with source code.<br />
<div>
<br /></div>
<div>
I make the following modifications to the IntelliJ editor settings:</div>
<div>
<br /></div>
<div>
<b>Show method separators</b></div>
<div>
This option shows horizontal lines between methods with which seperate methods are easily identified. To enable method separators do the following:</div>
<div>
<ol>
<li>Open the settings window</li>
<li>Open Editor -> appearance and check <i>Show method separators.</i></li>
</ol>
<div>
<b>High light usages of element at caret</b></div>
<div>
This option highlights all usages of the element where the caret is positioned. To enable this option:</div>
<div>
<ol>
<li>Open the settings window</li>
<li>Click Editor and check <i>Highlight usages of element ar caret.</i></li>
</ol>
<div>
<b>Highlight current scope</b></div>
</div>
<div>
This option highlights the current scope of a code block in the left gutter. To enable this option:</div>
<div>
<ol>
<li>Open the settings window</li>
<li>Click Editor and check <i>Highlight current scope.</i></li>
</ol>
<div>
<b>Disable allow placement of caret after end of line</b></div>
</div>
<div>
To disable the placement of the caret after the end of a line do the following:</div>
<div>
<ol>
<li>Open the settings window</li>
<li>Click Editor and uncheck <i>Allow placement of caret after end of line.</i></li>
</ol>
<div>
<b>Use and show soft wraps</b></div>
</div>
<div>
Soft wraps are useful when the editor window is smaller than the actual line length that can be displayed. The lines that exceed the editor window wraps to the following line.</div>
<ol>
<li>Open the settings window</li>
<li>Click Editor and check <i>use soft wraps in editor </i>and <i>Show all soft wraps.</i></li>
</ol>
<div>
<b>Tab limit</b></div>
<div>
The tab limit limits the maximum open tabs so the tabs remain manageable. To limit the maximum open tabs:</div>
<div>
<ol>
<li>Open the settings window</li>
<li>Click Editor -> Editor Tabs and specify a tab limit.</li>
</ol>
<div>
<b>Optimize imports on the fly</b></div>
</div>
<div>
This option automatically optimizes the imports when you are typing code. To enable this option:</div>
<div>
<ol>
<li>Open the settings window</li>
<li>Click Editor -> Auto Import and check <i>Optimize imports on the fly</i></li>
</ol>
<div>
The results of the above modifications can be seen in the screenshot below. I made the editor window smaller than usual to demonstrate the soft wraps.</div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1W9IPlCZ1tO68QIeBZcSN-FGypfwqFWgd8rGB86VXKlHz8LLxorNrhtXK7EjycQJC90Vo-0O6r5ATxHG7Mnjaa_V3AflpK3jhwCizlRM_npS2U3miWSIguqJUDu9ToLjFFNPc0fmi8As/s1600/editor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1W9IPlCZ1tO68QIeBZcSN-FGypfwqFWgd8rGB86VXKlHz8LLxorNrhtXK7EjycQJC90Vo-0O6r5ATxHG7Mnjaa_V3AflpK3jhwCizlRM_npS2U3miWSIguqJUDu9ToLjFFNPc0fmi8As/s1600/editor.jpg" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
In the project window I make the following modifications:</div>
<div>
<br /></div>
<div>
<b>Autoscroll to source</b></div>
<div>
This option lets me autoscroll to the editor window when a file is clicked.</div>
<div>
<br /></div>
<div>
<b>Flatten packages</b></div>
<div>
<b>Abbreviate qualified package names</b></div>
<div>
The above two option give a nice compact but complete overview of the package structure with abbreviated names. This can be seen in the following screenshot:</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhopJa3_E1y3sTc2iD3VdcVPIxzz6GdmQFDHtWvG1fvTWlo3HGZ6kK43iH6zdGgqycxcwdJsbfUCgzEYltHRyb2cySLHJtpKpga4Aihhdn1RvEinTjEKHWlVdmhLcULqLUcpXhVF425dfw/s1600/projectWindow.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhopJa3_E1y3sTc2iD3VdcVPIxzz6GdmQFDHtWvG1fvTWlo3HGZ6kK43iH6zdGgqycxcwdJsbfUCgzEYltHRyb2cySLHJtpKpga4Aihhdn1RvEinTjEKHWlVdmhLcULqLUcpXhVF425dfw/s1600/projectWindow.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Let me know which options you use.</div>
<div>
<br /></div>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com2tag:blogger.com,1999:blog-117760846317593301.post-51140685164775940952012-08-05T21:17:00.001+02:002012-08-05T21:17:37.532+02:00IntelliJ: Final parameters and variables<br />
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
Different teams require different coding styles and source code metrics. We have for example a rule which states that all method parameters should be final. Without going to discuss this rule (since your mileage may vary) I will show how IntelliJ can be used to enforce this rule.<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
There are two use cases here:<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
</div>
<ol>
<li>Adding the final keyword to all methods generated with IntelliJ.</li>
<li>Add the final keyword to existing methods.</li>
</ol>
<u></u><br />
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
To add the final keyword to parameters of generated methods do the following:<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
</div>
<ol>
<li>Open up the Project Settings dialog and navigate to Code Style -> Java.</li>
<li>Click the Code Generation tab.</li>
<li>In here you will find the Final modifier section.</li>
<li>Check the "Make generated parameters final" option.</li>
</ol>
<br />
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
If you now generate methods, IntelliJ will insert the final keyword before every parameter.<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
Besides adding the final keyword to every parameter in generated methods you can also add the final keyword to parameters in existing methods. To do this, do the following:<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
</div>
<ol>
<li>Open up the settings dialog and click Inspections (in Project settings)</li>
<li>Click copy to copy the Project default inspections and name the profile anything you want.</li>
<li>Click the Rest to Empty button to disable all inspections. Disabling all inspections is a quick way to only focus on a specific inspection if you want to apply just that specific inspection.</li>
<li>Enter 'final' in the search box</li>
<li>Under the "Code style issues" check the following rule: "Local variable or parameter can be final".</li>
<li>On the left make sure the option "Report method parameters" and/or "Report Local Variables".</li>
<li>Click OK.</li>
<li>Click Analyse -> Inspect code in the menu.</li>
<li>Make sure you select the Whole project and select the profile created in step 2.</li>
<li>Click OK.</li>
<li>In the inspection dialog you see all methods where the parameter could be final.</li>
<li>Right click the inspection and click "Apply fix 'Accept suggested final modifier'" to add the final modifier to all method parameters where it can be final.</li>
</ol>
<u></u><br />
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
Please note that the inspection does not add the final keyword to parameters which are reassigned since this gives compile errors. You could argue if this should be included in the inspection as well. I personally feel this can be handy to add final to all parameters regardless if they are changed or not. You can then afterwards fix all compile time issues you may have.</div>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-24995508803084815712012-07-30T18:54:00.000+02:002012-07-30T18:56:13.156+02:00IntelliJ productivity tips<br />
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
This is the first post in a series of many where I demonstrate a particular feature of IntelliJ. I use IntelliJ on a daily basis and knowing when to use particular features really helps improving productivity. Especially if you just start using IntelliJ you barely scratch the surface of what is possible. These series of posts help to get the most out of the IDE.<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
An often overlooked but powerful feature in IntelliJ is the structural search and replace. Suppose that there are lots of new instances of a particular class created. Sometimes it is better to use a static factory method instead.<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
For example: a rather large codebase I was working on had lots of new Integer() statements:<u></u><br />
<br /></div>
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public class SomeClass {
public static final Integer VARIABLE_1 = new Integer(10);
public static final Integer VARIABLE_2 = new Integer(20);
public static final Integer VARIABLE_3 = new Integer(30);
}
</code></pre>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
If the codebase has 10's, 100's or even 1000's of such statements, you can replace all of them with one single search and replace statement using structural search and replace. In short: with structural search and replace you can search/replace your entire codebase with knowledge about the code.<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
The above new instance creation can be replaced by doing the following:<u></u><u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br />
<ol>
<li><span style="background-color: white;">Open up the Structural Replace dialog by pressing Ctrl - Shift - M (on Windows) or Command - Shift - M (on OSX)</span></li>
<li><span style="background-color: white;">In the Search template dialog enter the following: new Integer($arguments$)</span></li>
<li><span style="background-color: white;">In the Replacement template enter the following: Integer.valueOf($arguments$)</span></li>
<li><span style="background-color: white;">Make sure you specify java as file type</span></li>
<li><span style="background-color: white;">In the Edit Variables dialog set the minimum and maximum count of the $arguments$ parameter to 1.</span></li>
<li><span style="background-color: white;">The above search template finds all occurrences of new Integer() with exactly one argument and replaces it with Integer.valueOf() taking into account the arguments.</span></li>
<li><span style="background-color: white;">Click find.</span></li>
<li><span style="background-color: white;">In the Find dialog you see all occurrences of new Integer($arguments$) that were found.</span></li>
<li><span style="background-color: white;">Click Do Replace all to replace all new Integer() to Integer.valueOf().</span></li>
</ol>
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<span style="background-color: white;">For an in-depth explanation of structural search and replace see </span><a href="http://www.jetbrains.com/idea/documentation/ssr.html" style="background-color: white; color: #1155cc;" target="_blank">http://www.jetbrains.com/idea/<wbr></wbr>documentation/ssr.html</a><span style="background-color: white;">.</span></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<u></u></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
<br /></div>
<div class="MsoNormal" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 13px;">
I hope you enjoy this series. If you have other useful tips please share them!</div>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-59242561009449081542012-05-01T20:34:00.000+02:002012-05-01T20:34:53.777+02:00Increasing user expectations<br />
Users are getting increasingly more demanding about the services and functionality that (online) organizations have to offer. This is especially true for organizations where users arrange most or all of their services online. Some examples are Internet banking, online insurance and travel agencies.<br />
<br />
Users expect this functionality:<br />
<br />
<ul>
<li>To be easy to use</li>
<li>That new features are added continuously and provide real value</li>
<li>Will work on their mobile devices like phones and tablets</li>
<li>Is tailored to their personal needs</li>
</ul>
<br />
This functionality is most of the time designed within the company itself and eventually, when developed and tested, deployed in production. In this model, the company expects that the functionality will meet the needs of most or all users. I believe this model is not sufficient anymore in the ever-increasing expectations of those users.<br />
<br />
One of the models to cope with this is to let users/developers themselves build the functionality they need. We also see a lot of this on the Internet where users build their own application/gadgets by using provided API’s. A prime example of this is of course Facebook.<br />
<br />
What if we extend this model to the enterprise? What if, for example, Internet Banking companies expose (some) of their functionality through API’s and let users develop functionality they really need? What kind of applications would arise out of this?<br />
<br />
I do not think this is a question of how but when. As some or most of you already know, Google owns a banking license. What does it mean for regular banks if Google or perhaps Facebook adopts such kind of platform for banking and/or insurance products? I think a whole new generation of users will make the transition to those companies. This indeed may have a large impact on the customer base of traditional organizations.<br />
<br />
Before organizations are ready to make such transitions, a large number of questions must be addressed:<br />
<br />
<ul>
<li>How do we secure access to API’s and data?</li>
<li>Which data do we want to expose?</li>
<li>Why would developers want to build applications for us? How do we compensate developers who are building great applications for us?</li>
<li>What about legal issues?</li>
<li>What technology do we use?</li>
<li>How do we change the mindset of our own people?</li>
<li>Etc.</li>
</ul>
<br />
And the most important question: when are organizations ready to adopt this model and radically change the way applications are delivered to end-users? Of course this change does not have to be a big bang but can and should be made incrementally.<br />
<br />
From a technology point of view, one of the ways to implement such eco-system is by adopting the Open Social specification. The Open Social specification defines:<br />
<br />
<ul>
<li>A social data model, which provides a standard representation of people their relationships and activities also known as a connected graph of people.</li>
<li>A set of standard API’s to access people, their relationships and activities available in REST and JavaScript API’s. Besides the JavaScript API for web applications, the REST API is particular interesting as enabler of mobile applications.</li>
<li>A standard to develop gadgets that encapsulate reusable application logic.</li>
</ul>
<br />
As an example, iGoogle is one of the platforms based on Open Social (in fact, Google donated their iGadgets container to the community which is Apache Shindig). IBM and Atlassian are also incorporating Open Social technology in their own products.<br />
<br />
<b>Conclusion</b><br />
<b><br /></b><br />
Since users become more and more demanding about the services and functionality that (online) organizations offer, organizations need to find other ways to provide that functionality instead of the traditional specification-build-deploy cycle. A possible way to do this is to let users themselves build the functionality they need. Open Social could be the technological enabler to facilitate this.<br />
<br />
However, the ultimate question remains: if and when are organizations ready to adopt a radical new strategy to provide functionality to its end-users.<br />
<br />
What is your opinion about this?<br />
<br />jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-32894311397528384262012-04-10T14:27:00.000+02:002012-04-10T14:29:01.367+02:00Flex: unittest a view with radio buttonsAt a recent project where I do some coaching, we wanted to unit test the validation logic present in view components. The validation logic is implemented as an array of validators which are triggered after some specific events take place. To test this we basically did the following:
<br />
<br />
<ol>
<li>Created a unit test (we are using FlexUnit)</li>
<li>Instantiate and initialize the view in the unit test</li>
<li>Populate the UI components with values to test</li>
<li>Trigger the validators</li>
</ol>
<div>
All seems well until we wanted to populate the selectedValue property of a RadioButtonGroup. This did not seem to work from within our unit tests. According to the documentation the selectedValue property can both be set and read from within code. Testing this logic inside a standalone MXML component and setting the selectedValue property did work. Unfortunately this did not help in our unit test because there it did not work.</div>
<div>
<br /></div>
<div>
Looking at the source code of the RadioButtonGroup I noticed that when setting the selectedValue property, the code loops over the associated RadioButtons. In our unit test the associated RadioButtons are not set (I expected that they were set actually). After digging some further I noticed the addInstance(instance:RadioButton):void method. This method apparently adds a RadioButton to the RadioButtonGroup. But where is it called? Somewhere by the Flex framework but where exactly was not obvious. Notice that this method is declared in the mx_internal namespace which means that this functionally may change in a future release. It also means however that we can still call this code ourselves.</div>
<div>
<br /></div>
<div>
To fix our test, the mx_internal namespace is added so the addInstance method can be called from within the test. With the addInstance method all RadioButtons which belong to the RadioButtonGroup can be added to the group. See the example below.</div>
<br/>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #a31515; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><?xml version=<span class="str">"1.0"</span>?></pre>
<pre><span class="lnum"> 2: </span><mx:VBox xmlns:mx=<span class="str">"http://www.adobe.com/2006/mxml"</span>></pre>
<pre class="alt"><span class="lnum"> 3: </span> <mx:RadioButtonGroup id=<span class="str">"genderRadioButtonGroup"</span>/></pre>
<pre><span class="lnum"> 4: </span> </pre>
<pre class="alt"><span class="lnum"> 5: </span> <mx:RadioButton id=<span class="str">"male"</span> groupName=<span class="str">"genderRadioButtonGroup"</span> label=<span class="str">"male"</span>></mx:RadioButton></pre>
<pre><span class="lnum"> 6: </span> <mx:RadioButton id=<span class="str">"female"</span> groupName=<span class="str">"genderRadioButtonGroup"</span> label=<span class="str">"female"</span>></mx:RadioButton></pre>
<pre class="alt"><span class="lnum"> 7: </span></mx:VBox></pre>
</div>
<br/>
And the code of the unit test:
<!-- code formatted by http://manoli.net/csharpformat/ -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #a31515; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span>package {</pre>
<pre><span class="lnum"> 2: </span>import flexunit.framework.TestCase;</pre>
<pre class="alt"><span class="lnum"> 3: </span> </pre>
<pre><span class="lnum"> 4: </span>import mx.core.mx_internal;</pre>
<pre class="alt"><span class="lnum"> 5: </span> </pre>
<pre><span class="lnum"> 6: </span>use <span class="kwrd">namespace</span> mx_internal;</pre>
<pre class="alt"><span class="lnum"> 7: </span> </pre>
<pre><span class="lnum"> 8: </span><span class="kwrd">public</span> <span class="kwrd">class</span> RadioButtonTest extends TestCase {</pre>
<pre class="alt"><span class="lnum"> 9: </span> <span class="kwrd">public</span> function RadioButtonTest() {</pre>
<pre><span class="lnum"> 10: </span> }</pre>
<pre class="alt"><span class="lnum"> 11: </span> </pre>
<pre><span class="lnum"> 12: </span> <span class="kwrd">public</span> function testPopulateRadioButton():<span class="kwrd">void</span> {</pre>
<pre class="alt"><span class="lnum"> 13: </span> </pre>
<pre><span class="lnum"> 14: </span> <span class="kwrd">var</span> myForm:MyForm = <span class="kwrd">new</span> MyForm();</pre>
<pre class="alt"><span class="lnum"> 15: </span> <span class="rem">// Initialize the UI component so that all child components are added to the form.</span></pre>
<pre><span class="lnum"> 16: </span> myForm.initialize();</pre>
<pre class="alt"><span class="lnum"> 17: </span> </pre>
<pre><span class="lnum"> 18: </span> <span class="rem">// Explicitly add the radiobuttons to the group, please note the use namespace mx_internal or else this</span></pre>
<pre class="alt"><span class="lnum"> 19: </span> <span class="rem">// method can not be called.</span></pre>
<pre><span class="lnum"> 20: </span> myForm.genderRadioButtonGroup.addInstance(myForm.male);</pre>
<pre class="alt"><span class="lnum"> 21: </span> myForm.genderRadioButtonGroup.addInstance(myForm.female);</pre>
<pre><span class="lnum"> 22: </span> </pre>
<pre class="alt"><span class="lnum"> 23: </span> myForm.genderRadioButtonGroup.selectedValue = <span class="str">"male"</span>;</pre>
<pre><span class="lnum"> 24: </span> </pre>
<pre class="alt"><span class="lnum"> 25: </span> assertEquals(<span class="str">"male"</span>, myForm.genderRadioButtonGroup.selectedValue);</pre>
<pre><span class="lnum"> 26: </span> }</pre>
<pre class="alt"><span class="lnum"> 27: </span>}</pre>
<pre><span class="lnum"> 28: </span>}</pre>
</div>
<div>
<br/>
<b>Conclusion</b></div>
<div>
Using the mx_internal namespace is not encouraged but sometimes can help to work around certain limitations, especially in test code. In the case of the RadioButtonGroup I would assumed things worked differently but unfortunately they did not. I doubt that this will be fixed in a future release regarding the state of Flex at the moment.</div>
<div>
<br /></div>
<div>
If you have another solution to the above problem please share it!</div>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0tag:blogger.com,1999:blog-117760846317593301.post-57789404269719603632012-03-29T07:22:00.000+02:002012-03-29T07:22:36.522+02:00Continuously looping video in WPFAt the moment I am building a Kinect based application using the Windows Presentation Foundation framework for a client. More details on this application later.<br />
<div>
<br /></div>
<div>
In that application we needed to show a continuously looping video. After looking through some documentation I used the following XAML construct to play and loop the video continuously:
<br />
</div>
<div>
<br /></div>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #a31515; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><MediaElement LoadedBehavior=<span class="str">"Play"</span>></pre>
<pre><span class="lnum"> 2: </span> <MediaElement.Triggers></pre>
<pre class="alt"><span class="lnum"> 3: </span> <EventTrigger RoutedEvent=<span class="str">"MediaElement.Loaded"</span>></pre>
<pre><span class="lnum"> 4: </span> <EventTrigger.Actions></pre>
<pre class="alt"><span class="lnum"> 5: </span> <BeginStoryboard></pre>
<pre><span class="lnum"> 6: </span> <Storyboard></pre>
<pre class="alt"><span class="lnum"> 7: </span> <MediaTimeline Source=<span class="str">"Instructions.avi"</span> RepeatBehavior=<span class="str">"Forever"</span> Storyboard.TargetName=<span class="str">"video"</span> /></pre>
<pre><span class="lnum"> 8: </span> </Storyboard></pre>
<pre class="alt"><span class="lnum"> 9: </span> </BeginStoryboard></pre>
<pre><span class="lnum"> 10: </span> </EventTrigger.Actions></pre>
<pre class="alt"><span class="lnum"> 11: </span> </EventTrigger></pre>
<pre><span class="lnum"> 12: </span> </MediaElement.Triggers></pre>
<pre class="alt"><span class="lnum"> 13: </span></MediaElement></pre>
</div>
<p>
Unfortunately this solution is not reliable. After some time it can took a while before the video starts playing again after it has ended. Sometimes the video stops playing completely. Some searching revealed that the MediaElement indeed is not reliable enough. Some alternatives where suggested, for example http://wpfmediakit.codeplex.com/.
</p>
<p>
The mediakit can indeed be a solution but there is a simpler way without adding a dependency on a third party framework. Instead of using a StoryBoard and a MediaTimeLine you can also manage the repetition yourself. The following code demonstrates this.
</p>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #a31515; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span><MediaElement x:Name=<span class="str">"instructionVideo"</span> Width=<span class="str">"320"</span> Height=<span class="str">"240"</span> Source=<span class="str">"Videos/Instructions.mp4"</span> LoadedBehavior=<span class="str">"Manual"</span> Loaded=<span class="str">"instructionVideo_Loaded"</span> MediaEnded=<span class="str">"instructionVideo_MediaEnded"</span> VerticalAlignment=<span class="str">"Bottom"</span> HorizontalAlignment=<span class="str">"Center"</span> Canvas.Top=<span class="str">"40"</span>/></pre>
</div>
<p>
The above XAML fragment is accompanied by the following code-behind:
</p>
<!-- code formatted by http://manoli.net/csharpformat/ -->
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: Consolas, "Courier New", Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #a31515; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<div class="csharpcode">
<pre class="alt"><span class="lnum"> 1: </span> <span class="kwrd">private</span> <span class="kwrd">void</span> instructionVideo_Loaded(<span class="kwrd">object</span> sender, RoutedEventArgs e)</pre>
<pre><span class="lnum"> 2: </span> {</pre>
<pre class="alt"><span class="lnum"> 3: </span> instructionVideo.Play();</pre>
<pre><span class="lnum"> 4: </span> }</pre>
<pre class="alt"><span class="lnum"> 5: </span> </pre>
<pre><span class="lnum"> 6: </span> <span class="kwrd">private</span> <span class="kwrd">void</span> instructionVideo_MediaEnded(<span class="kwrd">object</span> sender, RoutedEventArgs e)</pre>
<pre class="alt"><span class="lnum"> 7: </span> {</pre>
<pre><span class="lnum"> 8: </span> instructionVideo.Position = TimeSpan.FromSeconds(0);</pre>
<pre class="alt"><span class="lnum"> 9: </span> }</pre>
</div>
<p>
Instead of letting WPF manage the video, we specify a LoadedBehavior of Manual which means we can manage the starting and stopping of the video ourselves. To actually start the video the Loaded event handler is used which calls the Play method on the instructionVideo element. When the video reaches the end, the MediaEnded event is dispatched. In this event the Position is set back to 0 so the video starts playing from the beginning again. This proved to be a reliable way of continuously looping videos.
</p>
<p>
PS. the video in questions is in mp4 format and about 20 seconds in length which must loop all day long.
</p>jcraanehttp://www.blogger.com/profile/17776464801754441046noreply@blogger.com0