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

Events

View Events Video Library

Latest Articles - DZone

article thumbnail
Some Thoughts on Agile Planning
Agile Math The basic math of team-based agile is pretty simple. You can slice it several ways, but at the end of the day, one of these three basic formulas has to hold true. It’s all about time, cost, and scope… you get to decide which two constraints you want to lock, but then you have to derive the third. 1. backlog size / velocity = duration 2. duration * velocity = backlog size 3. backlog size / duration = velocity I generally suggest that agile is all about fixing time and cost, and deriving scope… but it doesn’t have to be that way. Feel free to derive time-based on a fixed backlog and known velocity. You can even derive a planning velocity based on fixed scope and time. This one is the riskiest, so be prepared to measure, adjust, and negotiate as the plan unfolds. Limiting WIP But here's the rub… when a team has too much work to do, and not enough time to do it, there is a cognitive dissonance between the messages of agile and what they see on the ground. We can say all day long that the PO gets to decide the “what” and the team gets to decide “how” and “how much”… but if management is fixing all three variables, the team isn’t going to buy in. Putting the Right People in Place One of the biggest mistakes that people make when working on any coding project is not having the right people in the right spots to help them out. It is absolutely necessary to use the talent and resources that are available to you in the most effective ways possible. Doing anything short of that can lead to major issues that you do not want to deal with. Instead of taking a risk, make sure you look at the pool of talent you have beforehand and begin to reassign people based on the skills that they clearly possess. You may be able to connect just the right pieces where they need to go in order to place people in the correct spots where they can be the most effective possible for you. If this is the case, then you will be in good shape when the time comes to use those people to get certain missions completed. You are responsible for putting people in a position where they can be as helpful and useful to you as possible. Observe their strengths and weaknesses to try to figure out exactly where that spot is. This may take some time, so make sure you have budgeted enough time for yourself to get these kinds of things figured out. It won’t always be easy, but it is the kind of work that you need to do to see real results on your projects. Rushing the Backlog Generally, here is what I ask from management out of the gate… give us three sprints to help the team come up with a backlog and establish a velocity, afterwards we’ll see what we have and decide how to proceed further. We’ll start by doing just enough backlog planning to identify a sprint or two worth of work and get the team working to establish a velocity. While the team begins work to establish their velocity, the PO aggressively moves to create the backlog. Almost never do I see a PO that can create a backlog all by themselves. Very often we need Product Managers, Architects, and Analysts to paint the complete picture. More often than not, I’ll ask these folks to work full time for as long as it takes to get the backlog together. I’ve got one PO team that has been at it for 8 weeks just to get ahead of the team, and define the release. Initially, the PO team is focused on feeding the team's high-value, high-risk stories… but as the backlog emerges we start rounding out the app. If all goes well, after several sprints we have a decent idea of what we have to build and the rate at which the team can complete the work. At that point, we apply one of our three formulas, baseline the plan, and go. Emergence or Convergence How far ahead of the team you need to be, largely depends on your business goals for the release. If you are highly uncertain about what you need to build, smaller backlogs are probably better, and the release planning process can be more nimble. Trying to predict stuff you just don’t know is a waste. In this case, agile is helping support an emergent outcome. Not all companies are going for an emergent outcome… Some want stability and predictability. In these cases, the PO team needs to plan further ahead of the team and adjust as the product is developed. The better we know where we are going, and what it is going to take to get there, the further out we can plan the backlog, and the more certain we can be about outcomes. Here agile is supporting a convergent outcome with a focus on risk reduction and predictability. One of the biggest problems I see with teams new to agile is that they act as if they are going for stability and predictability, when their product requires an emergent approach. Either requirements are not well understood or because of high technical risk or a ton of unknowns around how to implement them. Either way, you have to act as if the project is emergent until you gain enough knowledge to establish a more predictable plan. Not Knowing What You Don’t Know I’ve met a few teams lately where everyone is new and unfamiliar with the product and the code base. How do you set a schedule in this environment? The short answer is… you don’t. It’s okay not to know, but it’s not okay not to know forever. In this case, you better have a plan to get it figured out fast… It’s not reasonable to indefinitely ask the business to invest with no strategy for getting it done.
August 13, 2022
by Mike Cottmeyer
· 7,839 Views · 2 Likes
article thumbnail
Safeguard Your Xamarin Apps From Threats With Dotfuscator
We take a look at how mobile application developers working with Xamarin can secure their apps with this free, and awesome, tool.
Updated August 13, 2022
by Kaushal Shah
· 7,203 Views · 3 Likes
article thumbnail
Responsive Design and jQuery Mobile
The source code The slides for the talk "Mobile First!" is the new cry of web designers worldwide. But how do you do it? Do you have to scrap all of your current web skills? Is it magic created by wizard-like designers which could never be understood by mere mortals? Believe it or not, with the combination of jQuery Mobile and CSS3 Media Queries, you can easily create a site that looks good on a phone, tablet, or desktop. Does Mobile-First Still Matter? Yes! You still need to look to design all features of your programs with a mobile-first mentality. People are spending increasing amounts of time on their phones, and they expect the companies that create products for them to come up with something that will enable them to continue to view those products from their phones. If you are unable to do this for them, they may simply move on to another company that can provide them with that kind of functionality. You have a lot of choices to make when it comes to the specific features that you will use and embrace, but you need to consider how going mobile first can help bolster the chances of your application being used by the masses. General Responsive Web Features The web began as responsive. Now admittedly, the web didn't do very much, so being responsive when the Internet was mainly documents was easy. HTML documents naturally wrapped to the next line and flowed down the page. Along the way, things changed. Developers began designing sites in tools like PhotoShop and wanted perfect pixel renderings of those designs. The problem with pixels is that they are not very flexible. It has always been possible to use percentages instead of pixels, but they were clumsier to work with, so pixels remained the favorite. With HTML5 and CSS3 there is more support for responsive design. Lets Meta Tags Meta tags have been the favorite of the SEO crowd for some time. Meta tags are used to define keywords, descriptions, and even redirects. Here are some rules about meta tags: They always go in the section of the page They are never displayed They consist mostly of key/value pairs: name = key and content = value Viewport The viewport is a special type of meta tag which defines the screen of a mobile device. In the example program the viewport meta tag looks like: The attributes above mean: width=device-width - converts the pixels to CSS pixels initial-scale=1 - sets the scale level user-scalable=no - turns off scaling If the initial scale is some other value than 1, the zoom can be smaller or larger. If user-scalable is set to yes, then the user sets the zoom level by tapping, pinching, or whatever zoom gesture the browser supports. Media Query Media Queries are the workhorse of responsive design. A media query is a media type and at least one expression that limits the style sheets' scope. Here is an example: @media screen and (max-width: 1024px) and (orientation:portrait) { } The above media query means: For a screen media type Define the classes only if The width is less than 1023 AND the orientation is portrait The media query begins with @media then a media type, in this case, screen. Other types are all, braille, embossed, handheld, print, project, speech, tty, and tv. You can compose complex media queries using logical operators like not, and, and only. not - is used to negate an entire media query and - used to combine multiple media features together into a single media query only - used to apply a style only if the entire query matches Finally, there is the comma-separated list which behaves like an operator. If any media queries return true, the style sheets get applied. One pattern for applying the media queries is to define the query for the narrowest device first, then define it for a tablet, and finally a desktop. Now all of these definitions are pretty loose and open to interpretation. You may need to adjust them to fit your needs. If you run the demo on a high pixel phone like a Nexus 4, which has a display of 1280x768 resolution, why doesn't it display like a desktop? The key is the viewport meta tag. This tag, which is read by mobile browsers, redefines the pixels as CSS pixels. The precise number of CSS pixels varies by device, but on the iPhone, it is 320 and on the Nexus 4 it is 384, both of which are less than the minimum of 480 pixels to be defined as a tablet. jQuery Mobile Features So far we haven't looked at jQuery Mobile features. From the get go jQuery Mobile has had responsive features. Some of which are: grid - a simple way to build CSS-based columns that can also be responsive tables - selectively hide or shows table columns based on the display width panels - create a hidden page that slides left or right to reveal itself Grids Grids have been with jQuery Mobile since the beginning. They are essentially self sizing columns that dynamically resize themselves when the size of the page changes. The number of available columns ranges from two to five. To change the number of available columns simply change the class on the root p then add or remove a p from the collection. ui-grid-a = 2 columns ui-grid-b = 3 columns ui-grid-c = 4 columns ui-grid-d = 5 columns Tables Tables were added with the release of jQuery Mobile 1.3.0. They allow for the responsive display of tabular data. There are two basic types of tables: reflow which is the default and column toggle. Reflow tables lay the table data horizontally until it reaches a minimum size, then all of the data for each row is grouped together and it re-flows down the page. In column toggle mode, each column of a table can be given a separate priority, when the data can no longer fit horizontally, the column with the lowest priority number which is still visible is hidden. This continues until a minimum size is reached or there is only one column remaining. Panels A panel is a hidden page that reveals itself by sliding from the left or right onto the page. It can support nearly any jQuery Mobile widget. When the panel is displayed, clicking anywhere else on the page will close it. Best Practices Design styles beginning with "mobile first", then go wider Use "min-width" to constrain styles Prefer percentages and ems to pixels
August 13, 2022
by Troy Miles
· 16,001 Views · 1 Like
article thumbnail
Real-World ReactJS and Redux (Part 2)
This is the second in a series of blog posts about real-world ReactJS usage and what we've learned scaling our app at Threat Stack.
Updated August 13, 2022
by Cristiano Oliveira
· 14,954 Views · 1 Like
article thumbnail
Parsing JavaScript with JavaScript
Over the weekend I started working on llamaduck- a simple tool that aims to figure out whether your code will run on the newly released node 0.6.0. Eventually, it might be able to perform other compatibility assessment tasks as well, but I’m focusing on simple stuff first. Or at least I thought it was simple. The list of API changes since 0.4.x doesn’t seem that long and it should be easy enough to digest. But as it turns out, I spent almost all of Sunday just figuring out how to turn javascript into a beautiful analyzable AST. If you don’t know what an AST is – it’s a so-called abstract syntax tree, which means it should look identical regardless of what the actual syntax is. Although it will differ for different languages. So a CoffeeScript AST should look the same as JavaScript, but Python’s will differ. JavaScript Alterations and Changes There are so many JavaScript alterations and changes that one may need to make as they work through the program that it is undoubtedly challenging for some people to keep up with precisely what they are supposed to do to take care of things like this. What is known is that JavaScript alterations and changes can make life a lot more challenging for you in the short term, but it will pay off with a better product in the long run. What I discovered was that there were a lot of changes that needed to be made to get JavaScript to line up just the way that I wanted it to. There are so many small and technical aspects of this kind of coding that need to be adhered to down to the letter, and it is certainly not easy to pull it off until one has a lot of time to sit down and figure out what they need to do. JavaScript remains the dominant language used by computer programmers to put their materials out onto the Internet, so it made a lot of sense to me to start using this as a primary tool to get my own work done as well. I have continued to rely on JavaScript for projects both large and small, and I know that the only way that I get the most possible value out of it is to use it in ways that are effective for my customers. The increased use of JavaScript for all programmers is something that has led me to believe that I must continue working on ways to make the most out of my time with this program and the skills that I know can be applied in the best ways possible to get my desired results. When running JavaScript through the actual JavaScript program, it is common for programmers to run into some common issues. There are lines of exceptions that may appear at times, and there are other situations that arise which make it obvious that a certain piece of code is just not going to work as desired. If you run into that problem, just know that this is what the process is all about. Running the JavaScript through the program first is a great way to make sure those errors and omissions are eliminated from the final product. Look over every piece of this very carefully and make sure you understand what you are looking at. You may just discover that there is a lot more that you could be doing to help out your users after all. My research came up with three options: Take a parser generator and a JavaScript grammar, and hope for the best JSLint has a parser … somewhere around line 2000 Uglify-JS supposedly has a parser too The only viable option was uglify-js. It’s a neatly packaged node.js module that does a bit more than I need, but at least it’s got an easy-to-use parser with an exposed API interface. Score! Here’s an example of a file that outputs its own AST to give you a feel for what I’m talking about: var parser = require('uglify-js').parser; var util = require('util'); (function get_ast (path, callback) { require('fs').readFile(path, 'utf-8', function (err, data) { if (err) throw err; callback(parser.parse(data)); }); })('./example.js', function (data) { console.log(util.inspect(data, true, null)); }); The file parses itself and outputs a tree encoded as a javascript array (scroll past the insanity, there’s a bit more text there): [ 'toplevel', [ [ 'var', [ [ 'parser', [ 'dot', [ 'call', [ 'name', 'require', [length]: 2 ], [ [ 'string', 'uglify-js', [length]: 2 ], [length]: 1 ], [length]: 3 ], 'parser', [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 2 ], [ 'var', [ [ 'util', [ 'call', [ 'name', 'require', [length]: 2 ], [ [ 'string', 'util', [length]: 2 ], [length]: 1 ], [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 2 ], [ 'stat', [ 'call', [ 'function', 'get_ast', [ 'path', 'callback', [length]: 2 ], [ [ 'stat', [ 'call', [ 'dot', [ 'call', [ 'name', 'require', [length]: 2 ], [ [ 'string', 'fs', [length]: 2 ], [length]: 1 ], [length]: 3 ], 'readFile', [length]: 3 ], [ [ 'name', 'path', [length]: 2 ], [ 'string', 'utf-8', [length]: 2 ], [ 'function', null, [ 'err', 'data', [length]: 2 ], [ [ 'if', [ 'name', 'err', [length]: 2 ], [ 'throw', [ 'name', 'err', [length]: 2 ], [length]: 2 ], undefined, [length]: 4 ], [ 'stat', [ 'call', [ 'name', 'callback', [length]: 2 ], [ [ 'call', [ 'dot', [ 'name', 'parser', [length]: 2 ], 'parse', [length]: 3 ], [ [ 'name', 'data', [length]: 2 ], [length]: 1 ], [length]: 3 ], [length]: 1 ], [length]: 3 ], [length]: 2 ], [length]: 2 ], [length]: 4 ], [length]: 3 ], [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 4 ], [ [ 'string', './example.js', [length]: 2 ], [ 'function', null, [ 'data', [length]: 1 ], [ [ 'stat', [ 'call', [ 'dot', [ 'name', 'console', [length]: 2 ], 'log', [length]: 3 ], [ [ 'call', [ 'dot', [ 'name', 'util', [length]: 2 ], 'inspect', [length]: 3 ], [ [ 'name', 'data', [length]: 2 ], [ 'name', 'true', [length]: 2 ], [ 'name', 'null', [length]: 2 ], [length]: 3 ], [length]: 3 ], [length]: 1 ], [length]: 3 ], [length]: 2 ], [length]: 1 ], [length]: 4 ], [length]: 2 ], [length]: 3 ], [length]: 2 ], [length]: 3 ], [length]: 2 ] Conclusion Now we have a simple tree we can recursively analyze and look for incompatibilities. But before anything really practical can be done I need to figure out how to track variable scope. That’s really the hard bit because the code needs to check when variables become a critical section and then confirm that they do in fact eventually get used in a critical way. But once that nut is cracked llamaduck will be a neat little tool useful for many things. If you’ve got some coding inclination, I’d love a helping hand over at the llamaduck github repo. Related articles Lessons From A Review Of JavaScript Code (coding.smashingmagazine.com) ParserPlayground partial internals update (leuksman.com) Google Closure Introduction (googleclosure.wordpress.com) Announcing JesCov – JavaScript code coverage (olabini.com) Polyglot programming – combining functional, dynamic and imperative languages (mindscapehq.com)
August 13, 2022
by Swizec Teller
· 10,410 Views · 1 Like
article thumbnail
Openshift and AWS Lambda Deployment With Quarkus
Nowadays Quarkus is known as Supersonic Subatomic Java. It provides a lot of features to facilitate build and deployment.
Updated August 13, 2022
by Elina Valieva
· 12,685 Views · 5 Likes
article thumbnail
Neo4j and Cypher: Using MERGE With Schema Indexes/Constraints
I wrote about cypher’s MERGE function a couple of weeks ago, and over the last few days, I’ve been exploring how it works with schema indexes and unique constraints. An Exciting Time to Be a Developer There is so much that could be said about the merging of Neo4j and Cypher right now, but it is certainly reasonable to point out that this merger will likely result in many exciting developments in the programming world. Programmers virtually always appreciate it when they are given the products and tools they require to get their job done properly, and now is the time for steps like this to be taken. The fact that Neo4J and Cypher have decided to merge means that the upsides of both will soon be apparent. You deserve to use all of the best tools to make informed decisions about your next software project, and a great way to make it happen is to use what has been given to you regarding product functionality. This is to say that you can use both the upsides of Neo4J and Cypher to come up with the exact tools you need to make a difference in your sphere of influence. Could Other Products Soon Merge? There has been some strong demand for other software development products to consider merging. Coders and programmers want to use their favorite projects in exactly how they were meant to be used, and this means getting them to merge in ways that are useful to the programmers. They just want to be able to squeeze as much use out of each program as they possibly can. You want to make sure that you can see what is going on with your codes as you are directly applying them to whichever problem you are working on at this time. To be sure, it is not an easy task, but no one ever said it would be easy. The important thing is that you get the work done so that you can start to become more productive in the coding you are doing now. A common use case with Neo4j is to model users and events where an event could be a tweet, Facebook post, or Pinterest pin. The model might look like this: We’d like to ensure that we don’t get duplicate users or events, and MERGE provides the semantics to do this: MERGE (u:User {id: {userId}) MERGE (e:Event {id: {eventId}) MERGE (u)-[:CREATED_EVENT]->(m) RETURN u, e We’d like to ensure that we don’t get duplicate users or events and MERGE provides the semantics to do this: MERGE ensures that a pattern exists in the graph. Either the pattern already exists, or it needs to be created. import org.neo4j.cypher.javacompat.ExecutionEngine; import org.neo4j.cypher.javacompat.ExecutionResult; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.factory.GraphDatabaseFactory; import org.neo4j.helpers.collection.MapUtil; import org.neo4j.kernel.impl.util.FileUtils; ... public class MergeTime { public static void main(String[] args) throws Exception { String pathToDb = "/tmp/foo"; FileUtils.deleteRecursively(new File(pathToDb)); GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( pathToDb ); final ExecutionEngine engine = new ExecutionEngine( db ); ExecutorService executor = Executors.newFixedThreadPool( 50 ); final Random random = new Random(); final int numberOfUsers = 10; final int numberOfEvents = 50; int iterations = 100; final List userIds = generateIds( numberOfUsers ); final List eventIds = generateIds( numberOfEvents ); List merges = new ArrayList<>( ); for ( int i = 0; i < iterations; i++ ) { Integer userId = userIds.get(random.nextInt(numberOfUsers)); Integer eventId = eventIds.get(random.nextInt(numberOfEvents)); merges.add(executor.submit(mergeAway( engine, userId, eventId) )); } for ( Future merge : merges ) { merge.get(); } executor.shutdown(); ExecutionResult userResult = engine.execute("MATCH (u:User) RETURN u.id as userId, COUNT(u) AS count ORDER BY userId"); System.out.println(userResult.dumpToString()); } private static Runnable mergeAway(final ExecutionEngine engine, final Integer userId, final Integer eventId) { return new Runnable() { @Override public void run() { try { ExecutionResult result = engine.execute( "MERGE (u:User {id: {userId})\n" + "MERGE (e:Event {id: {eventId})\n" + "MERGE (u)-[:CREATED_EVENT]->(m)\n" + "RETURN u, e", MapUtil.map( "userId", userId, "eventId", eventId) ); // throw away for ( Map row : result ) { } } catch ( Exception e ) { e.printStackTrace(); } } }; } private static List generateIds( int amount ) { List ids = new ArrayList<>(); for ( int i = 1; i <= amount; i++ ) { ids.add( i ); } return ids; } } We create a maximum of 10 users and 50 events and then do 100 iterations of random (user, event) pairs with 50 concurrent threads. Afterward, we execute a query that checks how many users of each id have been created and get the following output: +----------------+ | userId | count | +----------------+ | 1 | 6 | | 2 | 3 | | 3 | 4 | | 4 | 8 | | 5 | 9 | | 6 | 7 | | 7 | 5 | | 8 | 3 | | 9 | 3 | | 10 | 2 | +----------------+ 10 rows Next, I added a schema index on users and events to see if that would make any difference, something Javad Karabi recently asked on the user group. CREATE INDEX ON :User(id) CREATE INDEX ON :Event(id) We wouldn’t expect this to make a difference as schema indexes don’t ensure uniqueness, but I ran it anyway t and got the following output: +----------------+ | userId | count | +----------------+ | 1 | 2 | | 2 | 9 | | 3 | 7 | | 4 | 2 | | 5 | 3 | | 6 | 7 | | 7 | 7 | | 8 | 6 | | 9 | 5 | | 10 | 3 | +----------------+ 10 rows If we want to ensure the uniqueness of users and events, we need to add a unique constraint on the id of both of these labels: CREATE CONSTRAINT ON (user:User) ASSERT user.id IS UNIQUE CREATE CONSTRAINT ON (event:Event) ASSERT event.id IS UNIQUE Now if we run the test, we’ll only end up with one of each user: +----------------+ | userId | count | +----------------+ | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 1 | | 5 | 1 | | 6 | 1 | | 7 | 1 | | 8 | 1 | | 9 | 1 | | 10 | 1 | +----------------+ 10 rows We’d see the same result if we ran a similar query checking for the uniqueness of events. As far as I can tell, this duplication of nodes that we merge on only happens if you try to create the same node twice concurrently. Once the node has been created, we can use MERGE with a non-unique index, and a duplicate node won’t get created. All the code from this post is available as a gist if you want to play around with it.
August 13, 2022
by Mark Needham
· 12,738 Views · 2 Likes
article thumbnail
Migrate Serialized Java Objects with XStream and XMT
Java serialization is convenient to store the state of Java objects. However, there are some drawbacks of serialized data: It is not human-readable. It is Java-specific and is not exchangeable with other programming languages. It is not migratable if fields of the associated Java class have been changed. These drawbacks make Java serialization not a practical approach to storing object states for real-world projects. In a product developed recently, we use XStream to serialize/deserialize Java objects, which solves the first and second problems. The third problem is addressed with XMT, an open source tool developed by us to migrate XStream serialized XMLs. This article introduces this tool with some examples. Computer Languages Need to be Simplified So many of the issues that we all run into when we are working on converting computer languages into something that can be better understood by human beings is the fact that computer languages need to be simplified if possible. These languages are great for the computers that speak back and forth with one another, but they don’t necessarily work out as well when humans try to become involved with them. Many humans end up confused and unable to make much progress at all on getting these systems cleared up. Thus, it is necessary to get them cleaned up and made more usable. There are people who are actively working on this problem right now, but in the meantime, we may simply have to deal with computers that can’t do everything we would like for them to do. XStream deserialization problem when class is evolved Assume a Task class below with a prioritized field indicating whether it is a prioritized task: package example; public class Task { public boolean prioritized; } With XStream, we can serialize objects of this class to XML like below: import com.thoughtworks.xstream.XStream; public class Test { public static void main(String args[]) { Task task = new Task(); task.prioritized = true; String xml = new XStream().toXML(task); saveXMLToFileOrDatabase(xml); } private static void saveXMLToFileOrDatabase(String xml) { // save XML to file or database here } } The resulting XML will be: true And you can deserialize the XML to get back task object: import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; public class Test { public static void main(String args[]) { String xml = readXMLFromFileOrDatabase(); Task task = (Task) new XStream(new DomDriver()).fromXML(xml); } private static String readXMLFromFileOrDatabase() { // read XML from file or database here } } Everything is fine. Now we find that a prioritized flag is not enough, so we enhance the Task class to be able to distinguish between high priority, medium priority and low priority: package example; public class Task { enum Priority {HIGH, MEDIUM, LOW} public Priority priority; } However, deserialization of previously saved XML is no longer possible since the new Task class is not compatible with the previous version. How does XMT Address the Problem XMT comes to the rescue: it introduces the class VersionedDocument to version serialized XMLs and handles the migration. With XMT, serialization of task object can be written as: package example; import com.pmease.commons.xmt.VersionedDocument; public class Test { public static void main(String args[]) { Task task = new Task(); task.prioritized = true; String xml = VersionedDocument.fromBean(task).toXML(); saveXMLToFileOrDatabase(xml); } private static void saveXMLToFileOrDatabase(String xml) { // save XML to file or database here } } For task class of the old version, the resulting XML will be: true Compared with the XML generated previously with XStream, an additional attribute version is added to the root element indicating the version of the XML. The value is set to "0" unless there are migration methods defined in the class as we will introduce below. When Task class is evolved to use enum based priority field, we add a migrated method like the below: package example; import java.util.Stack; import org.dom4j.Element; import com.pmease.commons.xmt.VersionedDocument; public class Task { enum Priority {HIGH, MEDIUM, LOW} public Priority priority; @SuppressWarnings("unused") private void migrate1(VersionedDocument dom, Stack versions) { Element element = dom.getRootElement().element("prioritized"); element.setName("priority"); if (element.getText().equals("true")) element.setText("HIGH"); else element.setText("LOW"); } } Migration methods need to be declared as a private method with the name in the form of "migrateXXX", where "XXX" is a number indicating the current version of the class. Here method "migrate1" indicates that the current version of the Task class is of "1", and the method migrates the XML from version "0" to "1". The XML to be migrated is passed as a VersionedDocument object which implements the dom4j Document interface and you may use dom4j to migrate it to be compatible with the current version of the class. In this migration method, we read back the "prioritized" element of version "0", rename it as "priority", and set the value as "HIGH" if the task is originally a prioritized task; otherwise, set the value as "LOW". With this migration method defined, you can now safely deserialize the task object from XML: package example; import com.pmease.commons.xmt.VersionedDocument; public class Test { public static void main(String args[]) { String xml = readXMLFromFileOrDatabase(); Task task = (Task) VersionedDocument.fromXML(xml).toBean(); } private static String readXMLFromFileOrDatabase() { // read XML from file or database here } } The deserialization works not only for XML of the old version but also for XML of the new version. At deserialization time, XMT compares the version of the XML (recorded in the version attribute as we mentioned earlier) with the current version of the class (maximum suffix number of various migrate methods), and runs applicable migrate methods one by one. In this case, if an XML of version "0" is read, method migrate1 will be called; if an XML of version "1" is read, no migration methods will be called since it is already up to date. As the class keeps evolving, more migration methods can be added to the class by increasing the suffix number of the latest migration method. For example, let's further enhance our Task class so that the priority field is taking a numeric value ranging from "1" to "10". We add another migrate method to the Task class to embrace the change: @SuppressWarnings("unused") private void migrate2(VersionedDocument dom, Stack versions) { Element element = dom.getRootElement().element("priority"); if (element.getText().equals("HIGH")) element.setText("10"); else if (element.getText().equals("MEDIUM")) element.setText("5"); else element.setText("1"); } This method only handles the migration from version "1" to version "2", and we do not need to care about version "0" anymore, since the XML of version "0" will first be migrated to version "1" by calling the method migrate1 before running this method. With this change, you will be able to deserialize the task object from XML of the current version and any previous versions. This article demonstrates the idea of how to migrate field change of classes. XMT can handle many complicated scenarios, such as migrating data defined in multiple tiers of class hierarchy, addressing class hierarchy change, etc. For more information of XMT, please visit http://wiki.pmease.com/display/xmt/Documentation+Home
August 13, 2022
by Robin Shen
· 21,258 Views · 1 Like
article thumbnail
A Guide to Maven 3 Beta
In just over six years, Apache Maven has become one of the most coveted tools for project build and reporting management. It’s been five years since the release of Maven 2, and now the Maven committers have released the next landmark version of the software. Incredible Improvements in Little Time It didn’t take long for Maven to become one of the most respected and desired tools in computer engineering. However, the product only continues to improve as Maven 3 is now available for those needing this extra computing power. The whole system just gets more and more interesting as time goes on, and that is exactly what people are most interested in when they look through different software options that are open to them. They just want something that they know will add to the amount of work that they can get done. We took some time to speak with the visionary founder of the Maven series of products, and we got some answers directly from him about how these products work and what kind of updates we might expect in the future. Believe it or not, just sitting down with him and getting some of these answers was a big help getting us to a place where we better understand the product. There is so much buzz and excitement about Maven 3 right now, and there should be. However, we wanted to hear directly from the creator of it to see which features we should be most excited about. We are so happy that he took the time to speak with us and review his innovative product. Hear what we learned today directly from the creator. The first beta release of Maven 3, which is now complete after seven public alphas, was released this week. Maven founder and Sonatype CTO Jason van Zyl answered some questions for DZone about Maven 3 earlier this month. Below are the main new feature categories of Maven 3. Drop-in Replacement Users of Maven 1.x may remember the bumpy transition to Maven 2 because of several fundamental changes. The Maven committers remember too, and they’ve put a lot of extra work into providing backward compatibility and making Maven 3 a simple drop-in replacement for Maven 2.x in most cases. van Zyl says this was “very difficult given how much of the internals we’ve changed.” Apart from fixing problems with duplicate dependency and plugin declarations, no changes are needed for your POMs. They’ve made the command line fully compatible between 2 and 3. Polyglot Maven Polyglot Maven is not a part of Maven 3 per se, but it is a tool from van Zyl’s company, Sonatype, that can be integrated with Maven 3 via an extension point. The extension points are a new feature in Maven 3 that support tools such as Tycho, Polyglot Maven, and Maven Shell. As you’ve probably guessed from the name, Polyglot Maven supports dynamic languages and is trying to provide first-class POM-mapped DSL (Domain Specific Language) support for Groovy, Scala, Clojure, Ruby, Xtext, and YAML. Polyglot Maven currently supports YAML. This is a welcome feature for developers who find the original XML format annoying. If you don’t, no big deal. Van Zyl also says it’s important for these DSLs to have repository interoperability and tooling to leverage M2Eclipse. M2Eclipse Maven 3 has changes related to embedding that make it work a lot better inside of M2Eclipse (the first Maven integration plugin for Eclipse). Maven 3 is now capable of a 200 to 300% performance boost while running in this plugin environment built specifically for Maven and the Eclipse IDE. M2Eclipse will provide some extra XML metadata in the Maven POM, which M2Eclipse only recognizes. This is one feature that enables high build performance. M2Eclipse also downloads all sources automatically and has a single-click new project creation feature for any of your dependencies. Maven Shell The Maven Shell is another extension point. It is Maven embedded in a long-lived shell process that caches parsed POMs, avoids start-up costs when invoking Maven repeatedly, supports Maven Archetype integration, provides Nexus integration, includes a built-in help system, and on Mac OS X, provides Growl support. Van Zyl says typical cases will see a 50% reduction in build times. Version 1.0 of the Maven Shell integrates the make-like reactor mode that builds only the modified modules. Support for project workflow, Hudson, Tycho, and Polyglot Maven are also present. Other improvements Developers working in multi-module or multi-pom projects won’t have to specify the parent version in every sub-module in Maven 3. Instead, you can add version-less parent elements. Maven 3 will also be able to see which POMs supplied which artifacts. In M2Eclipse, you can then deselect a certain contribution and select others. This is made possible through Maven 3’s decoupling of execution plans and execution. Maven 3 also includes extension points (mentioned above), which allow developers to hook up to different extension points instead of subclassing a plugin to alter the plugin’s behavior. You might, for example, have an extension point to alter how web.xml is processed through the WAR plugin. The source code in Maven 3 uses Google Guice for dependency injection and Peaberry to add OSGi capabilities to Guice. The whole dependency resolution is refactored into a standalone product by Sonatype called Mercury, for which Maven 3 is a client. Believe it or not, the Maven 3 codebase ended up being 1/3rd smaller than Maven 2. Maven 3.1 Looking toward the next release, Maven 3.1 will include a security manager with the settings.xml implementation as the default. Sonatype is planning an implementation that interacts with Nexus. Maven 3.1 will also introduce POM mixins, which make the configuration more maintainable and portable. Mixins will help solve the problem in Maven 2.0, where sharing configuration could only be done via inheritance. POM mixins are a type of POM composition that allows parameterized POM fragments to be injected into the current POM with a simple reference. References: "What's New in Maven 3" - Eingestellt von Reikje, DZone interview with Jason van Zyl, and "EclipseMagazine Interview with Jason van Zyl on the Maven Ecosystem"
August 13, 2022
by Mitch Pronschinske
· 46,586 Views · 2 Likes
article thumbnail
Key Takeaways: Adrian Cockcroft's talk on Netflix, CD, and Microservices
This article was originally published on 3/19/15
August 13, 2022
by Mitch Pronschinske
· 22,576 Views · 1 Like
article thumbnail
It's Official! Fat Arrows in JavaScript!
It’s official! We’re getting a new function syntax! The TC39 group (the panel charged with delivering ES 6) has reached a consensus on an abbreviated syntax for JavaScript function expressions. It's popularly known as the fat arrow syntax, and is based on a similar construct found in CoffeeScript. Make no mistake, I’m delighted that we will finally have an alternative to the unnecessary clunkiness and verbosity of the present grammar, but I can’t shake a nagging feeling that this proposal (in its current form) is flawed to the extent that it might actually make new developers more confused than they already were. I’ll run through the key features of this new construct, then explain my concerns and how they might be mitigated. There are Finally Fat Arrows in Java Java continues to add new features and make itself more useful to the public in due course. That said, there are many who have complained that the service never allowed them to put in the fat arrows that they wanted to. It was a glaring hole in the program, and it has now been clamped down on. People are finally able to get the fat arrow designs that they have been looking for without having to use another program to make it happen. Make sure you take a look at the full scope of what Java has to offer you as you explore the promise that it will be something even grander than anything else out on the marketplace at this time. You will want to take advantage of these new arrow designs if you can, and you will want to check up on all of the latest offerings from Java whenever possible. BS Alert Before starting out I should let you know that I’m going to make a lot of assertions about how fat arrows work. I’m reasonably confident that most of them are consistent with the latest proposal, but since research material is scant (I’m relying on the ES Wiki and the ES discuss list) and the examples are not testable (the traceur compiler does not yet support fat arrows) there are going to be some mistakes, for which I apologize upfront. I welcome corrections and will update the content as I get them. Thanks! How does it Work? The Syntax The fat arrow grammar has the following characteristics: 1. The arrow (=>) takes the place of the function keyword 2. Parameters are specified before the arrow, parentheses are required when there are zero, two or more parameters. 3. Block syntax (i.e. enclosing the function body in curly braces) is optional when the body comprises a single expression, otherwise it is required. 4. The return keyword is implied when the function body comprises a single expression. In all other cases returns must be used explicitly. Here are some simple examples. I’ve paired each fat arrow use case with the corresponding long-form syntax, although as we’ll see later the paired functions do not necessarily represent identical behavior. I’m defining variables with the var keyword for the sake of familiarity, but by the time ES6 is implemented you’re more likely to use let which allows variables to be defined with block scoping: //empty function var fat1 = () => {}; var long1 = function() {}; //return the square var fat2 = x => x * x; var long2 = function(x) {return x * x}; //add two numbers var fat3 = (a, b) => a + b; var long3 = function(a, b) {return a + b}; //return square root if x is a number, otherwise return x var fat4 = x => (typeof x == "number") ? Math.sqrt(x) : x; var long4 = function(x) { return (typeof x == "number") ? Math.sqrt(x) : x; }; Fat arrows bring a terse elegance to functional JavaScript… //return a new array containing the squares of the original... [1, 2, 3, 4, 5].map(x => x * x); //[1, 4, 9, 16, 25] //capitalize... ['caption', 'select', 'cite', 'article'].map(word => word.toUpperCase()); //['CAPTION', 'SELECT', 'CITE', 'ARTICLE'] //rewrite all instances of Fahrenheit as Celsius... function f2c(x) { var test = /(\d+(\.\d*)?)F\b/g; return x.replace(test, (str, val) => (val-32)*5/9 + "C"); } f2c("Store between 50F and 77F"); //"Store between 10C and 25C" (The last example is a rewrite of this traditional implementation). No Extras For You, Fat Arrow Not only do fat arrows use lightweight syntax – they also generate lightweight functions… No Constructors Functions created using fat arrow syntax have no prototype property, which means they can’t be used as constructors. If you try to use a fat arrow function as a constructor it throws a TypeError. No Arguments The argument’s object is not available within the execution context of a fat arrow function. This is not a huge loss; by the time ES 6 is in full swing, we can expect arguments to have been deprecated in favor of the rest (...) syntax. No Names There are Function Expressions, and then there are Named Function Expressions. Fat arrow functions have no place for a name, so they will always just be plain anonymous Function Expressions. The Value of This Functions defined with the fat arrow syntax have their context lexically bound; i.e. this value is set to the value of the enclosing scope (the outer function where present, otherwise the global object). //with long-form inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var longInner = function() { console.log(this); //this is global object }; longInner(); } } myObj.longOuter(); //with fat arrow inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var fatInner = () => console.log(this); //this is myObj fatInner(); } } myObj.longOuter(); It's a hard binding, which means if a fat arrow is used to define a method in an object literal it will continue to be bound to that object even when invoked from a borrowing object: var myObj = { myMethod: function() {return () => this;}, toString: () => "myObj" } var yourThievingObject = { hoard: myObj.myMethod, toString: () => "yourThievingObject" }; yourThievingObject.hoard(); //"myObj" Similarly the this value of a fat arrow function cannot be modified by means of call or apply: //traditional long inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var longInner = function() { console.log(this); //this is now myOtherObj } longInner.call(myOtherObj); } } myOtherObj = {}; myObj.longOuter(); //new fat inner function var myObj = { longOuter: function() { console.log(this); //this is myObj var fatInner = () => console.log(this); //this is still myObj fatInner.call(myOtherObj); } } myOtherObj = {}; myObj.longOuter(); So What’s the Problem? If you trawl the JavaScript section of Stack Overflow, you’ll find dozens of questions from puzzled developers trying to get their heads around JavaScript’s somewhat byzantine process of this assignment. So…remember how there are five ways to define the value of this in a function?… Syntax of function call Value of this 1. Method call: myObject.foo(); myObject 2. Baseless function call: foo(); global object (e.g. window) (undefined in strict mode) 3. Using call: foo.call(context, myArg); context 4. Using apply: foo.apply(context, [myArgs]); context 5. Constructor with new: var newFoo = new Foo(); the new instance (e.g. newFoo) …well now there’s a sixth… Syntax of function call Value of this 6. Fat Arrow: (x => x*x)(); this of lexical parent (A seventh rule was also proposed – naming the first argument of a fat arrow as ‘this’ would have bound the context to the base reference of a method call – but thankfully that option has been deferred). I appreciate the rationale behind lexical this binding. It’s intuitive, and if JavaScript was starting over, this would not be a bad way to do it. But at this point I’ve fallen in love with dynamic this values; they make functions gloriously flexible and are a great compliment to functional patterns, wherein functions form the bedrock of data, and other objects are mere fungibles. Moreover, if new developers are already discouraged by JavaScript’s perceived arbitrary assignment of context, yet another rule might be enough to finish them off for good. Bear in mind that fat arrow is sugar, and a very tasty sugar at that; it will be eagerly devoured by many developers long before the consequences of the sixth law of this has time to sink in. There’s another, related issue with the current proposal. Legacy functions (third party or otherwise) generally assume that their function arguments have dynamic this values. This enables them to invoke function arguments in any given context, which, amongst other things, is a useful way to add mixins. It’s true that Function.prototype.bind already offers a form of hard binding, but it does so explicitly; on the other hand, fat arrow’s hard binding is a side effect and it’s not at all obvious that it would break code like this: function mixin(obj, fn) { fn.call(obj); } //long form function mixin is dynamically bound var withCircleUtilsLong = function() { this.area = function() {return this.radius * this.radius * Math.PI}; this.diameter = function() {return this.radius + this.radius}; } //fat arrow function mixin is lexically bound (to global object in this case) var withCircleUtilsFat = () => { this.area = function() {return this.radius * this.radius * Math.PI}; this.diameter = function() {return this.radius + this.radius}; } var CircularThing = function(r) {this.radius = r}; //utils get added to CircularThing.prototype mixin(CircularThing.prototype, withCircleUtilsLong); (new CircularThing(1)).area(); //3.14 //utils get added to global object mixin(CircularThing.prototype, withCircleUtilsFat); (new CircularThing(1)).area(); //area is undefined How to Fix It OK, enough whining; time to make some proposals. Here are three ideas to remove, or at least mitigate, any negative effects of the new fat arrow context behavior. 1) (This one’s easy). Have fat arrow functions define this the same way as any regular Function Expression does – i.e. according to the five rules in the table above. It’s worth noting that CoffeeScript defined fat arrow as an alternative to their thin arrow (->) syntax. Thin arrow in CoffeeScript behaves, by and large, the same way as regular JavaScript Function Expressions. In contrast, ES6′s fat arrow is attempting to do at least two things at once – be the sole abbreviator of the syntax and redefine context assignment. To do one, or the other, would be less confusing. 2) (You probably saw this one coming too). Introduce thin arrow syntax at the same time. That way developers are drawn to the safer, less radical sugar which simply abbreviates their Function Expressions without throwing in secret surprises that mess with their contexts. Fat arrow expressions become the special case, not the default. This mail suggested the difference between fat and thin arrow would confuse folks, but by removing thin arrow we remove the stepping stone between dynamically bound long form functions and hardbound short form functions and the necessary conceptual leap becomes more radical. 3) (This one was proposed by @fb55 on the es discuss list). Only employ lexical scoping as a fallback when no other this binding is suggested. In other words, this would take the value of the base reference in a method call, or the context passed with a call or apply, but would defer to lexical scoping when invoked as a standalone function. (Standalone functions might just be the only part of JavaScript this assignment that actually needs fixing anyway). Wrap Up Is the primary goal of arrow functions brevity? or a hard-lexical binding? If it’s the former (and even if it isn't, a lot of developers will perceive that it is) then we should be careful not to overload it with new or surprising behavior. Oh and follow @fat.
August 13, 2022
by Angus Croll
· 17,580 Views · 1 Like
article thumbnail
Reactive vs. Synchronous Performance Test With Spring Boot
The author conducts two tests with differing service delay times to measure any difference in performance between reactive and synchronous programming.
Updated August 12, 2022
by Gonçalo Trincao Cunha
· 38,011 Views · 19 Likes
article thumbnail
Configuring Logback With Spring Boot
This deep dive of using Logback with Spring Boot includes how to use property files to alter the default Spring Boot settings and how to create custom configurations.
Updated August 12, 2022
by Dan Newton
· 462,499 Views · 27 Likes
article thumbnail
7 Best MQTT Client Tools Worth Trying
Find a suitable client tool for MQTT testing. Listed by desktop, browser, and command line categories, these tools are available for free (most, open source).
August 12, 2022
by Li Guowei
· 10,684 Views · 1 Like
article thumbnail
What Are Ephemeral Environments and How to Deploy and Use Them Efficiently
This article will cover ephemeral environments, their benefits in the development cycle, and how Environment as a Service enables fast and reliable deployment.
August 12, 2022
by Sorin Dumitrescu
· 6,468 Views · 2 Likes
article thumbnail
Discussing Backend for Front-End
Learn more about discussing backend for front-end.
August 12, 2022
by Nicolas Fränkel
· 12,677 Views · 7 Likes
article thumbnail
Write Your Kubernetes Infrastructure as Go Code - Extend cdk8s With Custom Constructs
Build a Wordpress deployment as a cdk8s construct.
August 12, 2022
by Abhishek Gupta DZone Core CORE
· 34,486 Views · 2 Likes
article thumbnail
How to Build a Custom Application Bar for Your Windows Phone App (the Easy Way)
There is nothing quite like building the perfect customized application bar to help you feel like you have made something truly special for your users. Indeed, many users report that they appreciate the efforts that companies go through to create useful utilities within the products that they already use. A customized application bar is a wonderful tool to include because it can be used to create something that users absolutely need, and also something that they have been requesting from the companies that they work with for quite some time. The application bar makes it easier for users to find the information and resources that they are looking for without all of the struggles, and that is a critical part of making the most out of any tool. In one of my recent projects, I was forced to use icons for the application bar buttons that didn’t fit into the circled template of the standard windows phone application bar. The icons have special circles themselves, and I am not allowed to change anything on those icons (you’re right, it is for the corporate app I am working on). That's why I needed to find another solution – and I started to write my own “application bar”. As I am using Telerik's windows phone controls, I knew that the rad image button had exactly the same behavior as the buttons in the standard application bar. That point was already saved, the only thing I needed to change was the button shape of the rad image button from rectangle to ellipse – done. This is the user control I created to achieve my goal: It was a bit tricky to get all the sizes to get a similar appearance, but it does look like the original one. The radimagebutton control also has a text that we can enter, but the text was too small or too close to the button, no matter what I did. That's why there is another row in my grid with the corresponding text. You may have recognized the image with the source “overflowdots.png” above. these are located in the windows phone icon folder (in Microsoft SDKs under program files). We need this icon to generate the transition the standard application bar has. It is done with two simple storyboards: All we need now is a proper event handler – the tap event of the image inside the control is perfect for that: private void overflowdots_tap(object sender, system.windows.input.gestureeventargs e) { if (customappbarborder.actualheight == 72) { fadecustomappbarbuttontextin.begin(); } else if (customappbarborder.actualheight == 102) { fadecustomappbarbuttontextout.begin(); } } I am using a border for the animation because with a grid it was not as fluent as I wanted. That's the whole code of the control I created. let’s have a look at the implementation: The first thing is an additional row in our layout root grid, where we can add our custom app bar control (set the height to “auto”). add this code to add the app bar: //declare the control: public customappbarwp8 customappbar; //add your data to the app bar: customappbar = new customappbarwp8(); customappbar.customappbarbackground = new solidcolorbrush(colors.green); customappbar.customappbarbuttonitem1text.text = "test 1"; customappbar.customappbarbuttonitem2text.text = "test 2"; customappbar.customappbarbuttonitem3text.text = "test 3"; customappbar.customappbarbuttonitem4text.text = "test 4"; customappbar.customappbarradimagebutton1.reststateimagesource = new bitmapimage(new uri("assets/appbar/microphone.png", urikind.relativeorabsolute)); customappbar.customappbarradimagebutton2.reststateimagesource = new bitmapimage(new uri("assets/appbar/save.png", urikind.relativeorabsolute)); customappbar.customappbarradimagebutton3.reststateimagesource = new bitmapimage(new uri("assets/appbar/delete.png", urikind.relativeorabsolute)); customappbar.customappbarradimagebutton4.reststateimagesource = new bitmapimage(new uri("assets/appbar/questionmark.png", urikind.relativeorabsolute)); //registering the tap events: customappbar.customappbarradimagebutton1.tap += customappbarradimagebutton1_tap; customappbar.customappbarradimagebutton2.tap += customappbarradimagebutton2_tap; customappbar.customappbarradimagebutton3.tap += customappbarradimagebutton3_tap; customappbar.customappbarradimagebutton4.tap += customappbarradimagebutton4_tap; //adding the app bar to the dedicated grid: appbargrid.children.add(customappbar); The standard application bar does fade out the text on a button tap, so we need to add this line in every tap event. otherwise, it would remain open all the time. if (customappbar.actualheight == 102) { customappbar.fadecustomappbarbuttontextout.begin(); } To get the same result on tapping outside our custom app bar, add the same code to your main grid’s mouse left button down event. This way, you have the same behavior as in the original control. Additional note: I needed to find a quick way to achieve this, that’s why I may have not been using best practices. I also used the rad image button control to speed things up. I will refine this control when I have more time available for it, as well as add a version without Telerik controls and add the menu items. If you have any idea on how to improve this, feel free to leave a comment below. Anyways, you can download the source of the code above here: https://github.com/msiccdev/customappbar_wp8 As always, I hope this will be helpful for some of you.
August 12, 2022
by Marco Siccardi
· 11,334 Views · 1 Like
article thumbnail
Google Cloud Messaging with Android
You have probably heard a lot of talk about the wonderful things the cloud can do for you, and you are probably curious about how those services may come into play in your daily life. If this sounds like you, then you need to know that cloud services are playing an increasingly important role in our lives, and we need to look at how they can change how we message one another. Many people are looking at Android cloud messaging as the next leap forward into a future where it is possible to reach out to the people we care about and save those messages directly in the cloud. Never miss the opportunity to communicate with someone who truly matters to you, and start using cloud storage to back up your messages. It is as simple as that! You might have heard of c2dm (cloud-to-device messaging), which basically allowed third-party applications to send (push) lightweight messages to their android applications. Well, c2dm as such is now deprecated and replaced with its successor up the evolutionary ladder: GCM, or google cloud messaging. GCM is a (free) service that allows developers to push two types of messages from their application servers to any number of android devices registered with the service: collapsible, "send-to-sync" messages non-collapsible messages with a payload up to 4k in size "Collapsible" means that the most recent message overwrites the previous one. A "send-to-sync" message is used to notify a mobile application to sync its data with the server. In case the device comes online after being offline for a while, the client will only get the most recent server message. If you want to add push notifications to your android applications, the getting started guide will walk you through the setup process step by step, even supplying you with a two-part demo application (client + server) that you can just install and play around with. The setup process will provide you with the two most essential pieces of information needed to run GCM: An API Key is needed by your server to send GCM push notifications A Sender ID is needed by your clients to receive GCM messages from the server Everything is summarized in the following screen you get after using the google API console: The quickest way to write both server and client code is to install the sample demo application and tweak it to your needs. In particular, you might want to at least do any of the following: Change the demo's in-memory datastore into a real persistent one. Change the type and/or the content of push messages. Change the client's automatic device registration on start-up to a user preference so that the handset user may have the option to register/unregister for the push notifications. We'll do the last option as an example. Picking up where the demo ends, here's a quick way to set up push preferences and integrate them into your existing android application clients. in your android project-resources ( res/xml) directory, create a preference.xml file such as this one: and the corresponding activity: // package here import android.os.bundle; import android.preference.preferenceactivity; public class pushprefsactivity extends preferenceactivity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); addpreferencesfromresource(r.xml.preferences); } } the above will provide the following ui: The "enable server push" checkbox is where your android application user decides to register for your push messages. Then, it's only a matter of using that preferences class in your main activity and doing the required input processing. the following skeleton class only shows your own code add-ons to the pre-existing sample application: // package here import com.google.android.gcm.gcmregistrar; // other imports here public class mainactivity extends activity { /** these two should be static imports from a utilities class*/ public static string server_url; public static string sender_id; private boolean push_enabled; /** called when the activity is first created. */ @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); // other code here... processpush(); } /** check push on back button * if pushprefsactivity is next activity on stack */ @override public void onresume(){ super.onresume(); processpush(); } /** * enable user to register/unregister for push notifications * 1. register user if all fields in prefs are filled and flag is set * 2. un-register if flag is un-set and user is registered * */ private void processpush(){ if( checkpushprefs() && push_enabled ){ // register for gcm using the sample app code } if(! push_enabled && gcmregistrar.isregisteredonserver(this) ){ gcmregistrar.unregister(this); } } /** check server push preferences */ private boolean checkpushprefs(){ sharedpreferences prefs = preferencemanager .getdefaultsharedpreferences(this); string name = prefs.getstring("sname", ""); string ip = prefs.getstring("sip", ""); string port = prefs.getstring("sport", ""); string senderid = prefs.getstring("sid", ""); push_enabled = prefs.getboolean("enable", false); boolean allfilled = checkallfilled(name, ip, port, senderid); if( allfilled ){ sender_id = senderid; server_url = "http://" + ip + ":" + port + "/" + name; } return allfilled; } /** checks if any number of string fields are filled */ private boolean checkallfilled(string... fields){ for (string field:fields){ if(field == null || field.length() == 0){ return false; } } return true; } } The above is pretty much self-explanatory. Now GCM push notifications have been integrated into your existing application. If you are registered, you get a system notification message at each server push, even when your application is not running. Opening up the message will automatically open your application: GCM is pretty easy to set up since most of the plumbing work is done for you. a side note: if you like to isolate the push functionality in its own sub-package, be aware that the GCM service gcmintentservice, provided by the sample application and responsible for handling GCM messages, needs to be in your main package (as indicated in the-set up documentation)—otherwise GCM won't work. When communicating with the sample server via an HTTP post, the sample client does a number of automatic retries using exponential back-off, meaning that the waiting period before a retry in case of failure is each time twice the amount of the preceding wait period, up to the maximum number of retries (5 at the time of this writing). You might want to change that if it doesn't suit you. It may not matter that much, though, since those retries are done in a separate thread (using asynctask) from the main UI thread, which therefore minimizes the effects on your mobile application's pre-existing flow of operations.
August 12, 2022
by Tony Siciliani
· 30,095 Views · 1 Like
article thumbnail
Getting started with PHP framework codeigniter
I have always worked with core PHP and was always reluctant to use any CMS (Joomla, Drupal, etc). Coincidentally I never got a chance to work on any of the frameworks in PHP. But in the current project at work, we have decided to use CodeIgniter. CodeIgniter is a lightweight open source web application framework. In short, it gives you a directory structure of a proper MVC pattern along with a lightweight built-in templating engine of its own. MVC pattern helps developers to separate business logic and the presentation layer. It requires a very minimal setup, unlike the famous PHP framework, Zend. Zend is mostly used in developing enterprise applications and is a vast framework, hence making the learning curve more difficult. On the other hand, CodeIgniter is easy to set up and easier to learn. Using Proper Frameworks It is so very important to apply the proper frameworks to any project that you are working on. When you use the best coding frameworks, you can accomplish a lot more than you might have ever dreamed was possible. Eliminating some of the noise and distractions that can take you away from truly accomplishing all that you need to is a big step in the right direction, and you will find that getting started with the right frameworks is probably what you need to do as a first step towards that goal. Otherwise, you will find yourself floundering for the right answers, and your projects just won’t turn out the way that you might have hoped that they would. Let’s Get started with CodeIgniter Of course, the first step is to download the codeigniter framework. You can download the latest stable version of Codeigniter from the following URL http://codeigniter.com/downloads/ . It will be a compressed file (zip file) that will be downloaded, just unzip it and keep it in a folder, say Codeigniter. Make sure you keep it inside the htdocs or webserver’s directory. Now it's time to configure the Codeigniter which initial settings to start working on. To do so, open the file config.php in your favorite editor. The file resides inside system/application/config directory. You will see an array called $config which stores all the configuration information, we will change only the following values and leave the rest as it is. /* |-------------------------------------------------------------------------- | Base Site URL |-------------------------------------------------------------------------- | */ //don't forget the TRAILING slash (/) $config['base_url'] = "http://localhost/codeigniter/"; Trust me, that shall be all to get you started. Some blogs/sites have shown many changes in this file, but you can play around with them when needed. You can change a lot about your application from this single file. Like you can store the session information inside a database, by simply setting up the config var $config['sess_use_database'] as TRUE, which is FALSE by default. You can also change the name of the session table from default “ci_sessions” to anything you like. Since none of the web applications runs without database, let me show you how to configure a database in this setup. I decided to pick this up in the next tutorial, but since it's pretty straightforward, let’s do it. To configure the database, open database.php which is located in the same directory as config.php i.e. system/application/config . Now change the values of the following array keys with the actual values of your MySQL server. $active_group = "default"; $active_record = TRUE; $db['default']['hostname'] = "localhost"; $db['default']['username'] = ""; //database username $db['default']['password'] = ""; //database password $db['default']['database'] = ""; //name of the database $db['default']['dbdriver'] = "mysql"; $db['default']['dbprefix'] = ""; //any table prefix, if you want to keep one $db['default']['pconnect'] = TRUE; $db['default']['db_debug'] = TRUE; $db['default']['cache_on'] = FALSE; $db['default']['cachedir'] = ""; $db['default']['char_set'] = "utf8"; $db['default']['dbcollat'] = "utf8_general_ci"; As you see the database configuration was also simple. Now it's time to develop a simple application using the CI framework. At the very beginning of this post I mentioned that CodeIgniter gives you an MVC pattern structure, so every part has a separate folder. Let us create a simple controller class to start with. To do this, let's create a class called Hello which will be written in the file called hello.php, stored inside system/application/controllers/ folder. The content of the file can be : (you can have a different class, after all, it's just a PHP class). class hello extends Controller { function __construct() { //call parent constructor parent::__construct(); } function index() { $output['header'] = "My page's header"; $output['content'] = "Here is the content of the webpage"; //load from from the system/application/views/hello.php $this->load->view('hello',$output); } } Dissect the code Now let us understand the code line by line. It's a controller class called hello which extends the default parent class called Controller. Extending the Controller class facilitates the execution of this controller. The constructor of this call simply loads the constructor of the parent class, which apparently is Controller. Next is the index(); function which has a special meaning in the CI framework. If it's present in a controller, it is executed automatically when the controller is loaded/executed. Now we output the data using the view part of the MVC pattern. if you notice the above code loads a view called hello which is a file kept inside the system/application/views/ folder. The file name should be the same as the name of the controller. And the data is provided in the form of an array, where header,content are the template variables, as shown below in the hello.php The above view renders the data which is passed on by the calling controller. Now let's try and test if everything works as we expected, phew! Open your browser and hit http://localhost/codeigniter/index.php/hello/ If everything is well, you should see a webpage, with a header and body content as specified in the controller. Wonder, how did that get rendered? CodeIgniter provides a very nice routing mechanism based on REST. The URL is so that you can call a specific controller and a method from inside the controller. But if you notice, in the above URL we have mentioned only the controller name i.e. hello, and not the function name index(). As mentioned previously, This is due to the fact that index(); function gets called automatically if it exists. Might it have been another function called render then the above URL would have been changed to http://localhost/codeigniter/index.php/hello/render/ The above URL which now call the render(); function from the hello controller. CodeIgniter was easy, no? If you think that was tough, just go through the steps again and I am sure you will understand. Since CI is the easiest framework and it lets you get started very quickly with the development. Happy Development!
August 12, 2022
by Sachin Khosla
· 11,241 Views · 1 Like
  • Previous
  • ...
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

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

Let's be friends:

  • RSS
  • X
  • Facebook
×