Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

and many more ....

Featured FREE Whitepapers

What's New Here?


JAXB – No Annotations Required

There appears to be a misconception that annotations are required on the model in order to use a JAXB (JSR-222) implementation. The truth is that JAXB is configuration by exception, so annotations are only required when you want to override default behaviour. In this example I’ll demonstrate how to use JAXB without providing any metadata. Domain Model I will use the following domain model for this example. Note how there are no annotations of any kind. Customer Customer is the root object in this example. Normally we would annotate it with @XmlRootElement. Later in the demo code you will see how we can use an instance of JAXBElement instead. package blog.defaults;import java.util.List;public class Customer {private String firstName; private String lastName; private List<PhoneNumber> phoneNumbers;public String getFirstName() { return firstName; }public void setFirstName(String firstName) { this.firstName = firstName; }public String getLastName() { return lastName; }public void setLastName(String lastName) { this.lastName = lastName; }public List<PhoneNumber> getPhoneNumbers() { return phoneNumbers; }public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) { this.phoneNumbers = phoneNumbers; }}PhoneNumber I have purposefully given the fields in this class nonsense names, so that later when we look at the XML you will be able to see that by default the element names are derived from the properties and not the fields. package blog.defaults;public class PhoneNumber {private String foo; private String bar;public String getType() { return foo; }public void setType(String type) { = type; }public String getNumber() { return bar; }public void setNumber(String number) { = number; }}Demo Code Since we haven’t used @XmlRootElement (or @XmlElementDecl ) to associate a root element with our Customer class we will need to tell JAXB what class we want to unmarshal the XML document to. This is done by using one of the unmarshal methods that take a Class parameter (line 14). This will return a J AXBElement , the Customer object is then accessed by calling getValue on it (line 15). To marshal the object back to XML we need to ensure that it is wrapped in a JAXBElement to supply the root element information (line 17). package blog.defaults;import javax.xml.bind.*; import javax.xml.namespace.QName; import;public class Demo {public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Customer.class);StreamSource xml = new StreamSource("src/blog/defaults/input.xml"); Unmarshaller unmarshaller = jc.createUnmarshaller(); JAXBElement<Customer> je1 = unmarshaller.unmarshal(xml, Customer.class); Customer customer = je1.getValue();JAXBElement<Customer> je2 = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(je2, System.out); }} input.xml/Output The following is the input to and output from running the demo code. The first thing we see is that it is a very reasonable XML representation of the data, there aren’t any JAXB artifacts. By default JAXB will marshal everything as XML elements, and based on our PhoneNumber class we see that the element names were derived from the property names. <?xml version="1.0" encoding="UTF-8"?> <customer> <firstName>Jane</firstName> <lastName>Doe</lastName> <phoneNumbers> <number>555-1111</number> <type>work</type> </phoneNumbers> <phoneNumbers> <number>555-2222</number> <type>home</type> </phoneNumbers> </customer>Further Reading If you enjoyed this post then you may also be interested in:The majority of the articles on this blog describe how to leverage the power of JAXB’s metadata to support different use cases, I invite you to check them out: you are interested in specifying metadata without using annotations, you may be interested in EclipseLink JAXB (MOXy)’s external mapping document:Extending JAXB – Representing Metadata as XML Extending JAXB – Representing Metadata as JSONReference: JAXB – No Annotations Required from our JCG partner Blaise Doughan at the Java XML & JSON Binding blog....

Answering with Mockito

When you are writing unit tests, you must keep in mind to not have dependencies to external components. To avoid this we use mock frameworks which for me the easiest one to use is Mockito. In this post we are going to see an ‘advanced’ technique used in Mockito to return same argument instance on a mocked method using Answer interface. Suppose we are writing unit tests for class which manages Person and Job classes and as operation it uses a DAO class for inserting the relationship class (M:N) between Person and Job called PersonJob. For example class under test will look something like: public PersonJob createPersonJob(Person person, Job job) { .. some job .. PersonJob personJob = new PersonJob(person, job); return this.personJobDao.create(personJob); } So in this case it seems obvious that you need to mock personJobDao. Let’s create the mock and record the interaction: public class WhenAJobIsAssignedToPerson { @Test public void relationship_should_be_made_persistent() { PersonJobDao personJobDao = mock(PersonJobDao.class); when(personJobDao.create(any(PersonJob.class))).thenReturn(???) PersonJobManager personJobManager = new PersonJobManager(); personJobManager.setPersonJobDao(personJobDao); Person person = new Person(); Job job = new Job(); PersonJob personJob = personJobManager.createPersonJob(person, job); assertThat(personJob.getPerson(), is(person)); assertThat(personJob.getJob(), is(job)); } } Yes as you can see you don’t know what to return, because instance is created by class under test and in the test method you don’t know which instance is created by createPersonJob method. To solve this problem, you need to use thenAnswer instead of thenReturn method: public class WhenAJobIsAssignedToPerson { @Test public void relationship_should_be_made_persistent() { PersonJobDao personJobDao = mock(PersonJobDao.class); when(personJobDao.create(any(PersonJob.class))).thenAnswer(new Answer<PersonJob>() { public PersonJob answer(InvocationOnMock invocation) throws Throwable { return (PersonJob) invocation.getArguments()[0]; } }); PersonJobManager personJobManager = new PersonJobManager(); personJobManager.setPersonJobDao(personJobDao); Person person = new Person(); Job job = new Job(); PersonJob personJob = personJobManager.createPersonJob(person, job); assertThat(personJob.getPerson(), is(person)); assertThat(personJob.getJob(), is(job)); } }Note that Answer interface requires you to implement answer method, which in our case simply returns the first argument ( PersonJob instance) of personJobDao. create method. Now we can write assertions in peace without worrying about returned instance. Reference: Answering with Mockito from our JCG partner Alex Soto at the One Jar To Rule Them All blog....

Hash Length Extension Attacks

In this post I will try to leave the summer slump behind and focus on more interesting things than complaining about the weather – hash length extension attacks. Hash length extension attacks are nothing complicated or high sophisticated, to be honest it is just about how to use hash functions. As discussed in one of my former posts there are multiple types of hash functions, but this post focuses on cryptographic hash functions. We are not going to analyze the structure of Merkle–Damgard constructions, which the majority of current cryptographic hash functions are based on. The necessary facts to know are the followings:hash functions operate on fixed block sizes input data is split into to parts to fit the block size if input data (or one of its part) is smaller than block size, the missing bytes are padded the hash value represents the internal state of the hash function!This implies the option to continue the hash computation with the knowledge of the hash value, even if the original input remains unknown. The only thing that has to be done is to reset the internal state of the hash function to the one of the hash value. This is just half the truth, since if we aren’t aware of the input data, we have no clue how much padding was needed to complete the hash operation. The hash function did the following (after a call to e.g. in Java engineDigest()): continue until the last block is reachedpad the last block output the digest reset the internal stateWhat really has been hashed was something like this h(m) = data + padding If we would like to continue the hash we have to guess the length of data to determine exactly the padding. Once we guessed the length right we can extend the hash to the following h(m) = (data + padding) + ourExtension + newPadding Fortunately the padding format has to be deterministic (in order to recreate the hash value by passing the same input data), so knowing the length of data enables the recreation of the padding. After performing these steps we have the complete internal state of the hash function when outputting the digest. How to use this In 2009 Rizzo and Duong used a hash length extension attack to compromise Flickr. For the sake of simplicity let’s make the following assumption: A Web Service protects their REST API by computing some kind of Message Authentication Code (MAC) based on a hash function MAC = h(SECRET_PASSWORD + Resource) A valid REST query to a protected resource looks like this http://…/someAction?resource=validMACsOnly&mac=xxxxxxxx A user is only able to perform the desired action on the resource if the attached MAC is valid. Attacking this seems to be a brute force task by trying to guess the secret password… Attack With the knowledge how to extend a hash value it is possible to provide a valid MAC without knowing the secret password. For this to work it is necessary to reset the used hash function with the internal state when outputting the digest. Therefore we set the value of the mac parameter as the internal state of the hash function. With these preconditions we are able to compute a valid MAC. But that’s just half the way, since the server only grants access if the computed MAC belongs to the passed parameters of resource. So, as a next step we have to guess the original padding. To get that padding we simply try all possible paddings until one of them fits. If we manage to get the padding right we are done. After the old padding (which was necessary to fill the block of the known block size) we start, as a consequence, in a new block. So the server verifies the following h(m) = (oldData + recoveredPadding) + (ourExtension + newPadding) Remember h(m) = (oldData + recoveredPadding) is the old data that lead to the known MAC. The extended data starts in a new block, this means the old padding is considered to be part of the input data, not a padding at all. And here is how the modified query looks like: http://…/someAction?resource=validMACsOnly\x80\x00…\x00\x00\x00\x00\x00\x00\x00\xD8&mac=xxxxxxxx Some words on the padding:the padding starts with \x80 the needed padding space is filled with \x00s the last 8 bytes represent the data length in bits (without padding)Code For every one eager to play with this, here is the code to compute valid extensions. For PoC a common SHA1 library was patched to gain access to its internal state. The modified class is taken from a Java Security Provider. import java.nio.charset.Charset; import; import java.util.Formatter;/** * Hash length extension attack - PoC. * * @author Christopher Meyer - * @version 0.1 * * Jul 25, 2012 */ public class HashLengthExtension {/** * Secret key. */ private static final String KEY = "NoNeedToRecoverKey"; /** * String to be MACed together with the key. */ private static final String TOMAC = "SecuredResource"; /** * Extension string to be added to the MAC. */ private static final String EXTENSION = "TheResourceRemainsUnsecured"; /** * Static Hash algorithm instance. */ private static final SHA1 HASH_ALGO = new SHA1(); /** * Blocksize of the algorithm in bytes. */ private static final int BLOCKSIZE = 64; /** * Padding. */ private static final byte[] PADDING = new byte[136];static { // the first padding byte is 0x80 - by definition PADDING[0] = (byte) 0x80; }/** * Computes a valid input that extends a given hash. * * @param args the command line arguments */ public static void main(String[] args) throws DigestException { byte[] extensionBytes = EXTENSION.getBytes(Charset.forName("UTF8")); byte[] toMACBytes = TOMAC.getBytes(Charset.forName("UTF8")); byte[] originalMAC = createMAC(toMACBytes); System.out.println("Original MAC : " + buildHexString(originalMAC));byte[] macCandidate; byte[] hashInput; int pointer = 0;System.out.println("Recover digest state..."); HASH_ALGO.engineReset(); // set internal state to the one of the original MAC HASH_ALGO.state[0] = bytesToInt(originalMAC[0], originalMAC[1], originalMAC[2], originalMAC[3]); HASH_ALGO.state[1] = bytesToInt(originalMAC[4], originalMAC[5], originalMAC[6], originalMAC[7]); HASH_ALGO.state[2] = bytesToInt(originalMAC[8], originalMAC[9], originalMAC[10], originalMAC[11]); HASH_ALGO.state[3] = bytesToInt(originalMAC[12], originalMAC[13], originalMAC[14], originalMAC[15]); HASH_ALGO.state[4] = bytesToInt(originalMAC[16], originalMAC[17], originalMAC[18], originalMAC[19]); HASH_ALGO.bytesProcessed = BLOCKSIZE;System.out.println("Compute extension MAC..."); HASH_ALGO.engineUpdate(extensionBytes, 0, extensionBytes.length); // compute the extended hash macCandidate = HASH_ALGO.engineDigest(); System.out.println("Extended MAC : " + buildHexString(macCandidate));System.out.println("Trying to find suitable input...."); // determine the necessary input.... int j = 0; for (int i = 1; i <= PADDING.length; i++) { hashInput = new byte[toMACBytes.length + i + 8 + extensionBytes.length]; pointer = 0;/** * Compute new input */ // # add original message System.arraycopy(toMACBytes, 0, hashInput, pointer, toMACBytes.length); pointer += toMACBytes.length; // # add padding System.arraycopy(PADDING, 0, hashInput, pointer, i); pointer += i; // # add length of user data (8 bytes) // j is the computed length of the original message in bits // (blockSize - padding length - 8 length bytes) j = (BLOCKSIZE - i - 8) << 3; // the first word is 0 in our case, due to only 32 bit int hashInput[pointer] = 0; hashInput[pointer + 1] = 0; hashInput[pointer + 2] = 0; hashInput[pointer + 3] = 0; hashInput[pointer + 4] = (byte) ((j >>> 24)); hashInput[pointer + 5] = (byte) ((j >>> 16)); hashInput[pointer + 6] = (byte) ((j >>> 8)); hashInput[pointer + 7] = (byte) (j); pointer += 8; // # add extension System.arraycopy(extensionBytes, 0, hashInput, pointer, extensionBytes.length); pointer += extensionBytes.length;// # check guess if (isMACCorrect(macCandidate, hashInput)) { System.out.println("==> Hash input : " + buildHexString(hashInput)); System.out.println("==> Padding Length: " + i); System.out.println("==> Secret Length : " + (BLOCKSIZE - toMACBytes.length - i - 8)); break; } } }/** * Convert a byte[] to int. * * @param bytes 4 bytes array to be converted * @return Integer representation of the byte[] */ private static int bytesToInt(byte... bytes) { return (int) ((0xFF & bytes[0]) << 24 | (0xFF & bytes[1]) << 16 | (0xFF & bytes[2]) << 8 | (0xFF & bytes[3])); }/** * Checks if the input results creates the expected MAC. * * @param macToCheck Expected MAC * @param msg Modified input for MAC function (secret key remains unknown) * @return True if the modified input creates the expected MAC * @throws DigestException */ private static final boolean isMACCorrect(final byte[] macToCheck, final byte[] msg) throws DigestException { boolean result = true; byte[] referenceHash = createMAC(msg); System.out.println("Reference hash: " + buildHexString(referenceHash));if (referenceHash.length != macToCheck.length) { result = false; } else { for (int i = 0; i < referenceHash.length; i++) { if (referenceHash[i] != macToCheck[i]) { result = false; break; } } }return result; }/** * Converts a byte[] to its Hex representation * @param bytes Bytes to be converted * @return Hex String of the passed byte[]. */ private static String buildHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length); Formatter formatter = new Formatter(sb);for (Byte tmpByte : bytes) { formatter.format("%02x ", tmpByte); }return sb.toString(); }/** * Creates a weak MAC of the form h(secret + msg). * * @param msg Message to get MACed * @return Weak MAC * @throws DigestException */ private static final byte[] createMAC(final byte[] msg) throws DigestException { byte[] utf8KeyBytes = KEY.getBytes(Charset.forName("UTF8"));HASH_ALGO.engineReset(); HASH_ALGO.engineUpdate(utf8KeyBytes, 0, utf8KeyBytes.length); HASH_ALGO.engineUpdate(msg, 0, msg.length); return HASH_ALGO.engineDigest(); } }Running the exmaple above creates the following output: run: Original MAC : a9 fb f9 84 91 f3 8b 56 ee f7 34 73 ba fc 4b bf d5 0b 03 b8 Recover digest state... Compute extension MAC... Extended MAC : ba 92 0b 97 e9 27 c6 a8 91 84 6a 58 ed e3 e1 62 13 45 27 65 Trying to find suitable input.... Reference hash: 91 6c 2c d4 0b 7e a0 ec d4 57 ad f3 e6 b6 db 2e 57 e6 0e 9d Reference hash: 46 98 09 77 59 ff 57 f7 b1 28 26 80 f0 9d 5e 96 14 5a 9d 77 Reference hash: 43 75 ea fc 1c 1d e6 51 a1 c0 9d 38 9f 31 c7 52 17 e6 9f a9 Reference hash: 6d 5c f9 9b af 26 6f ca dd 61 1c 16 71 a3 ac fb 60 82 57 76 Reference hash: 78 95 9a e5 81 30 00 5d 61 0b 5c 81 5e 9a 2d 3d 71 da e3 5a Reference hash: 2d cf 0b 01 09 be 59 5d 76 e0 64 ee 44 27 44 12 48 96 cb 73 Reference hash: 11 e3 08 1b f4 0f 8f ad a8 9e 66 4b 2f 97 ec 14 f5 59 4c 68 Reference hash: 59 96 fc e8 dd d3 db ae 43 9c 34 a4 1e cc 15 cf af 49 49 3f Reference hash: e8 cb 3b cf b1 72 9b d1 21 33 75 39 7e 6d 23 b8 e1 a3 fc c7 Reference hash: f0 f4 55 e9 12 65 7d 90 65 4b 50 34 af 38 93 a1 dd 73 74 6d Reference hash: 5a c9 7a d6 f0 6d d7 a8 17 c6 d8 fd ba 59 17 ae 6b ee e8 2b Reference hash: 50 6c b9 07 d9 cd c9 bb 0a 6b 9b 89 ce 9f 07 7f d1 b8 48 10 Reference hash: c0 81 31 4c 65 f5 11 d0 13 56 7e 73 d6 04 f0 ff 6c 76 7a ac Reference hash: 0e f1 eb 4f 8f 6f 7f 6f 5e b5 1d 3f 9c 15 ab 44 63 97 35 c3 Reference hash: f1 4e f2 81 e0 6c 0a f3 ae ef b4 db c7 09 1e 1d 34 7c 79 7d Reference hash: 30 b5 54 5e 79 a6 d9 26 b6 9f 12 9a cc a6 44 ef 85 d7 17 b6 Reference hash: 09 19 1e 6a 92 79 a5 34 d5 6c a2 84 c7 0d c2 49 15 dc 6d d2 Reference hash: 56 4b 7f b7 f0 af 6f 2d 1d cd 0e d4 10 e6 d2 d3 db b0 f9 c0 Reference hash: c1 51 a7 47 2d de b3 43 a0 77 28 9a 6c 55 49 f2 61 5c 69 1a Reference hash: 37 f2 7f 80 b2 50 3a 22 60 ae 10 67 74 1d e6 19 b1 32 de 48 Reference hash: a3 91 d6 20 ff 4b da 92 19 a0 fb bf 58 46 0a 5a fe 7c eb e1 Reference hash: 10 d9 aa 0a ff db 8f 0d 4c 3c f6 90 3a e9 40 bc 1a 12 d7 65 Reference hash: ba 92 0b 97 e9 27 c6 a8 91 84 6a 58 ed e3 e1 62 13 45 27 65 ==> Hash input : 53 65 63 75 72 65 64 52 65 73 6f 75 72 63 65 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 08 54 68 65 52 65 73 6f 75 72 63 65 52 65 6d 61 69 6e 73 55 6e 73 65 63 75 72 65 64 ==> Padding Length: 23 ==> Secret Length : 18Using URL encoding the resulting String from hashInput is SecuredResource%80%01%08TheResourceRemainsUnsecured, the original resource, 23 padding bytes (including the %80), 8 length bytes and the new resource. Thus we get (64 bytes block size – 23 padding bytes – 8 length bytes) * 8 bit = 264 bit original data (secret + resource) == 01 08 in Hex representation. Lessons learned Don’t misuse cryptography by creating your own secure constructs. Use well approved functions and constructs. In this case using an HMAC function would have been the better approach instead of introducing an own MAC. A very good blog entry on this topic can be found at WhiteHat Security Blog. Reference: Hash Length Extension Attacks from our JCG partner Christopher Meyer at the Java security and related topics blog....

EclipseLink MOXy as a JAXB provider

EclipseLink MOXy is a JAXB provider and is a compelling alternative to the default JAXB provider built into JDK. First a simple test to marshal a Java object to XML: This is the model: @XmlRootElement(name='MemberDetailsRequest', namespace='') @XmlAccessorType(XmlAccessType.FIELD) public class MemberDetailsRequest {public MemberDetailsRequest() { }public MemberDetailsRequest(Long id) { = id; }private Long id;public Long getId() { return id; }public void setId(Long id) { = id; } } and the test for marshaling: package org.bk.memberservice.binding;import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static;import;import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller;import org.bk.memberservice.message.MemberDetailsRequest; import org.junit.Test;public class TestJaxbRequestBinding {@Test public void testJaxbBinding() throws Exception{ JAXBContext jaxbContext = JAXBContext.newInstance(MemberDetailsRequest.class); assertThat((jaxbContext instanceof org.eclipse.persistence.jaxb.JAXBContext), is(true)); Marshaller marshaller = jaxbContext.createMarshaller(); MemberDetailsRequest memberDetailsRequest = new MemberDetailsRequest(); memberDetailsRequest.setId(1L); StringWriter writer = new StringWriter(); marshaller.marshal(memberDetailsRequest, writer); String marshalledXml = writer.toString(); assertThat(marshalledXml, containsString('MemberDetailsRequest')); } }The highlighted line checks to make sure that MOXy’s JAXBContext is the one created. So to use MOXy as the JAXB provider, first step is to get the jar files, I had a little difficulty finding the MOXy jars to be used in a Maven pom file, this is what worked for me: <repository> <id>EclipseLink Repo</id> <url></url> <name>EclipseLink Repo</name> </repository><dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.moxy</artifactId> <version>2.4.0</version> </dependency> The next step is to instruct to set MOXy as the JAXB provider. This is done by placing a along with any of the JAXB model classes. So in this case, I have placed a into my package holding MemberDetailsRequest class, and the contents are the following: javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactoryand that’s it! Reference: EclipseLink MOXy as a JAXB provider from our JCG partner Biju Kunjummen at the all and sundry blog....

Spring Integration – Session 2 – More Hello Worlds

This is a follow up to Spring Integration Session 1 The first session was a simple Hello World application using Spring Integration. I want to take it a little further by considering a few more scenarios around it. So the first change to the Hello World application is to add in a Gateway component. To quickly revisit the earlier test program: package;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.message.GenericMessage; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("helloworld.xml") public class HelloWorldTest { @Autowired @Qualifier("messageChannel") MessageChannel messageChannel;@Test public void testHelloWorld() { Message<String> helloWorld = new GenericMessage<String>("Hello World"); messageChannel.send(helloWorld); } }In the lines highlighted above, the test is dependent on a Spring Integration specific component – a Message Channel, and in the test an explicit Spring Integration Message is constructed and sent to the Message Channel. There is a little too much coupling with Spring Integration which is the Messaging System here. A Gateway component provides a facade to the messaging system, shielding the user application(in this case the Unit test) from the details of Messaging System – the messaging channel, Message and explicit sending of a message. An example first to illustrate how the test will look with a Gateway component in place: package;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("helloworld.xml") public class HelloWorldTest {@Autowired Greeter greeter;@Test public void testHelloWorld(){ this.greeter.sendGreeting("Hello World"); } }The Greeter interface above is the Gateway component. Now that this component has been introduced there is no dependency to Spring Integration in this test – there is no mention of Message, Message Channel in the code at all. The Gateway component is also a very simple Java Interface defined this way: package;public interface Greeter { public void sendGreeting(String message); }So now the question is who takes care of creating the messaging and sending the message to a message channel – it is through Spring Integration configuration: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="" xmlns:xsi="" xmlns:int="" xmlns:int-stream="" xsi:schemaLocation=""><int:channel id="messagesChannel"></int:channel> <int:gateway service-interface="" default-request-channel="messagesChannel"></int:gateway> <int-stream:stdout-channel-adapter channel="messagesChannel" append-newline="true"/></beans>The highlighted line above creates the Gateway component out of the Greeter interface, a proxy is created in the background which handles everything that was being done explicitly earlier – creating the messaging and sending the message to the message channel. Now to add a little more complexity to the Hello World sample: Consider the following test: package;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("helloworld.xml") public class HelloWorldTest {@Autowired Greeter greeter;@Test public void testHelloWorld(){ System.out.println("Started.."); long start = System.nanoTime(); for (int i=0;i<10;i++){ this.greeter.sendMessage(String.format("Hello World %d",i)); } System.out.println("Completed.."); System.out.println(String.format("Took %f ms", (System.nanoTime()-start)/10e6)); } }This is same as the previous unit test, except that in this case the “Hello World” message is being dispatched 10 times. The supporting Spring Integration configuration file is the following: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="" xmlns:xsi="" xmlns:int="" xmlns:int-stream="" xsi:schemaLocation=""><int:publish-subscribe-channel id="messagesChannel"/> <int:gateway service-interface="" default-request-channel="messagesChannel"></int:gateway> <int-stream:stderr-channel-adapter channel="messagesChannel" append-newline="true"/> <int-stream:stdout-channel-adapter channel="messagesChannel" append-newline="true"/> </beans>If I run this test now, the output is along these lines:The lines in red are being printed to syserr and in black are being printed to sysout. So the question is why are some of them going to sysout and some of them going to syserr and why not to both? The answer is because of the type of channel – “messagesChannel” above is a “Direct Channel” in the Spring Integration terminology and has “Point to point” semantics. The point-to-point semantics basically means that when a message comes into the Messaging Channel, only 1 receiver gets the message – so in this case either the standard out adapter OR the standard err adapter ends up printing the message that is coming into the message channel. So to print to both adapters, the fix is to simply change the semantics of the channel – instead of a Point to Point channel, make it a Publish-Subscribe channel, which is a channel broadcasting out a message to multiple receivers. The change is very simple using Spring Integration: file:/C:/learn/scratch/target/test-classes/org/bk/htmlencode/content.txt <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="" xmlns:xsi="" xmlns:int="" xmlns:int-stream="" xsi:schemaLocation=""><int:publish-subscribe-channel id="messagesChannel"/> <int:gateway service-interface="" default-request-channel="messagesChannel"></int:gateway> <int-stream:stderr-channel-adapter channel="messagesChannel" append-newline="true"/> <int-stream:stdout-channel-adapter channel="messagesChannel" append-newline="true"/> </beans>The output now will be the messages being printed to BOTH sysout and syserr So this completes the introduction to a Gateway component, Direct Channel and Publish Subscribe channel. Reference: Spring Integration – Session 2 – More Hello Worlds from our JCG partner Biju Kunjummen at the all and sundry blog....

String memory internals

This article is based on my answer on StackOverflow. I am trying to explain how String class stores the texts, how interning and constant pool works. The main point to understand here is the distinction between String Java object and its contents – char[] under private value field. String is basically a wrapper around char[] array, encapsulating it and making it impossible to modify so the String can remain immutable. Also the String class remembers which parts of this array is actually used (see below). This all means that you can have two different String objects (quite lightweight) pointing to the same char[]. I will show you few examples, together with hashCode() of each String and hashCode() of internal char[] value field (I will call it text to distinguish it from string). Finally I’ll show javap -c -verbose output, together with constant pool for my test class. Please do not confuse class constant pool with string literal pool. They are not quite the same. See also Understanding javap’s output for the Constant Pool. Prerequisites For the purpose of testing I created such a utility method that breaks String encapsulation: private int showInternalCharArrayHashCode(String s) { final Field value = String.class.getDeclaredField("value"); value.setAccessible(true); return value.get(s).hashCode(); }It will print hashCode() of char[] value, effectively helping us understand whether this particular String points to the same char[] text or not. Two string literals in a class Let’s start from the simplest example. Java code String one = "abc"; String two = "abc";BTW if you simply write "ab" + "c", Java compiler will perform concatenation at compile time and the generated code will be exactly the same. This only works if all strings are known at compile time. Class constant pool Each class has its own constant pool – a list of constant values that can be reused if they occur several times in the source code. It includes common strings, numbers, method names, etc. Here are the contents of the constant pool in our example above: const #2 = String #38; // abc //... const #38 = Asciz abc;The important thing to note is the distinction between String constant object ( #2) and Unicode encoded text "abc" ( #38) that the string points to. Byte code Here is generated byte code. Note that both one and two references are assigned with the same #2 constant pointing to "abc" string: ldc #2; //String abc astore_1 //one ldc #2; //String abc astore_2 //twoOutput For each example I am printing the following values: System.out.println("one.value: " + showInternalCharArrayHashCode(one)); System.out.println("two.value: " + showInternalCharArrayHashCode(two)); System.out.println("one" + System.identityHashCode(one)); System.out.println("two" + System.identityHashCode(two));No surprise that both pairs are equal: one.value: 23583040 two.value: 23583040 one: 8918249 two: 8918249Which means that not only both objects point to the same char[] (the same text underneath) so equals() test will pass. But even more, one and two are the exact same references! So one == two is true as well. Obviously if one and two point to the same object then one.value and two.value must be equal. Literal and new String()   Java code Now the example we all waited for – one string literal and one new String using the same literal. How will this work? String one = "abc"; String two = new String("abc");The fact that "abc" constant is used two times in the source code should give you some hint… Class constant pool Same as above. Byte code ldc #2; //String abc astore_1 //onenew #3; //class java/lang/String dup ldc #2; //String abc invokespecial #4; //Method java/lang/String."<init>":(Ljava/lang/String;)V astore_2 //twoLook carefully! The first object is created the same way as above, no surprise. It just takes a constant reference to already created String ( #2) from the constant pool. However the second object is created via normal constructor call. But! The first String is passed as an argument. This can be decompiled to: String two = new String(one);Output The output is a bit surprising. The second pair, representing references to String object is understandable – we created two String objects – one was created for us in the constant pool and the second one was created manually for two. But why, on earth the first pair suggests that both String objects point to the same char[] value array?! one.value: 41771 two.value: 41771 one: 8388097 two: 16585653It becomes clear when you look at how String(String) constructor works (greatly simplified here): public String(String original) { this.offset = original.offset; this.count = original.count; this.value = original.value; }See? When you are creating new String object based on existing one, it reuses char[] value. Strings are immutable, there is no need to copy data structure that is known to be never modified. Moreover, since new String(someString) creates an exact copy of existing string and strings are immutable, there is clearly no reason for the two to exist at the same time. I think this is the clue of some misunderstandings: even if you have two String objects, they might still point to the same contents. And as you can see the String object itself is quite small. Runtime modification and intern()   Java code Let’s say you initially used two different strings but after some modifications they are all the same: String one = "abc"; String two = "?abc".substring(1); //also two = "abc"The Java compiler (at least mine) is not clever enough to perform such operation at compile time, have a look: Class constant pool Suddenly we ended up with two constant strings pointing to two different constant texts: const #2 = String #44; // abc const #3 = String #45; // ?abc const #44 = Asciz abc; const #45 = Asciz ?abc;Byte code ldc #2; //String abc astore_1 //oneldc #3; //String ?abc iconst_1 invokevirtual #4; //Method String.substring:(I)Ljava/lang/String; astore_2 //twoThe fist string is constructed as usual. The second is created by first loading the constant "?abc" string and then calling substring(1) on it. Output No surprise here – we have two different strings, pointing to two different char[] texts in memory: one.value: 27379847 two.value: 7615385 one: 8388097 two: 16585653Well, the texts aren’t really different, equals() method will still yield true. We have two unnecessary copies of the same text. Now we should run two exercises. First, try running: two = two.intern();before printing hash codes. Not only both one and two point to the same text, but they are the same reference! one.value: 11108810 two.value: 11108810 one: 15184449 two: 15184449This means both one.equals(two) and one == two tests will pass. Also we saved some memory because "abc" text appears only once in memory (the second copy will be garbage collected). The second exercise is slightly different, check out this: String one = "abc"; String two = "abc".substring(1);Obviously one and two are two different objects, pointing to two different texts. But how come the output suggests that they both point to the same char[] array?!? one.value: 11108810 two.value: 8918249 one: 23583040 two: 23583040I’ll leave the answer to you. It’ll teach you how substring() works, what are the advantages of such approach and when it can lead to big troubles. Lessons learned String object itself is rather cheap. It’s the text it points to that consumes most of the memory String is just a thin wrapper around char[] to preserve immutability new String("abc") isn’t really that expensive as the internal text representation is reused. But still avoid such construct. When String is concatenated from constant values known at compile time, concatenation is done by the compiler, not by the JVM substring() is tricky, but most importantly, it is very cheap, both in terms of used memory and run time (constant in both cases)Reference: String memory internals from our JCG partner Tomasz Nurkiewicz at the Java and neighbourhood blog....

Database Abstraction and SQL Injection

I have subscribed to various user groups of jOOQ’s competing database abstraction tools. One of which is ActiveJDBC, a Java implementation of Active Record design pattern. Its maintainer Igor Polevoy recently claimed that: SQL injection is a web application problem, and not directly related to an ORM. ActiveJDBC will process any SQL that is passed to it.(See the discussion here: Is that really true? Should the database abstraction layer delegate SQL injection prevention to the client application?   SQL Injection Background SQL injection is a problem that most of us developers have had to deal with one time or another in their professional lives. Wikipedia explains the problem nicely. Given the following piece of Java code (or any other language): statement = "SELECT * FROM users WHERE name = '" + userName + "';"Imagine that “userName” is a variable taken from an HTTP request. Blindly pasting an HTTP request parameter gives way to simple attacks as these: -- attacker sends this code in the userName field: userName = "a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't"-- resulting in the following statement: statement = "SELECT * FROM users WHERE name = 'a';" + "DROP TABLE users;" + + "SELECT * FROM userinfo WHERE 't' = 't';"This doesn’t happen to you? Maybe not. But the problem is seen quite often on Stack Overflow. More than 2000 results when searching for “SQL injection”: So even if you know how to prevent it, someone on your team may not. OK, but … it’s not that bad if one out of 500 statements is badly written by some programmer that was oblivious of this threat? Think again. Have you ever heard of a tool called sqlmap? This tool will find any problematic page within your application within a couple of seconds/minutes/hours, depending on the severity of your injection problem. Not only that, once it has found problematic pages, it will be able to extract ALL kinds of data from your database. I mean ALL kinds of data. A selection of sqlmap features:Support to enumerate users, password hashes, privileges, roles, databases, tables and columns. Support to search for specific database names, specific tables across all databases or specific columns across all databases’ tables. This is useful, for instance, to identify tables containing custom application credentials where relevant columns’ names contain string like name and pass. Support to download and upload any file from the database server underlying file system when the database software is MySQL, PostgreSQL or Microsoft SQL Server. Support to execute arbitrary commands and retrieve their standard output on the database server underlying operating system when the database software is MySQL, PostgreSQL or Microsoft SQL Server. Yes! If you suffer from SQL-injection-unsafe code, an attacker can seize your server under some circumstances!! In our company, we’ve tried sqlmap in a sandbox environment against some open source blog software with known vulnerabilities. We’ve managed to seize the server in no time, without writing a single line of SQL   Database Abstraction and SQL Injection OK, now that I have your attention, let’s think again about what Igor Polevoy said: SQL injection is a web application problem, and not directly related to an ORM. ActiveJDBC will process any SQL that is passed to it. Yes, he may be right. Given that ActiveJDBC is a slim wrapper for JDBC, allowing to do nice CRUD simplifications, such as these (taken from their website): List<Employee> people = Employee.where("department = ? and hire_date > ? ", "IT", hireDate) .offset(21) .limit(10) .orderBy("hire_date asc");Did you spot the risk for SQL injection? Right. Even if it uses bind values for underlying PreparedStatements, this tool is as unsafe as JDBC. You can avoid SQL injection, if you’re careful. Or you can start concatenating strings all over. But you have to be aware of that! How does jOOQ handle situations like these? The jOOQ manual explains how bind values are handled explicitly or implicitly. Here are some examples: // Implicitly creating a bind value for "Poe" .from(T_AUTHOR) .where(LAST_NAME.equal("Poe"));// Explicitly creating a (named) bind value for "Poe" .from(T_AUTHOR) .where(LAST_NAME.equal(param("lastName", "Poe")));// Explicitly inlining "Poe" in the generated SQL string .from(T_AUTHOR) .where(LAST_NAME.equal(inline("Poe")));The above examples will yield SELECT * FROM T_AUTHOR WHERE LAST_NAME = ? SELECT * FROM T_AUTHOR WHERE LAST_NAME = ? SELECT * FROM T_AUTHOR WHERE LAST_NAME = 'Poe'In the case where “Poe” is inlined, escaping is handled by jOOQ, to prevent syntax errors and SQL injection. But jOOQ also supports injecting SQL strings directly in generated SQL. For instance: // Inject plain SQL into jOOQ .from(T_AUTHOR) .where("LAST_NAME = 'Poe'");In this case, SQL injection can occur just as with JDBC   Conclusion In essence, Igor is right. It is the (client) application developer’s responsibility to be aware of SQL injection issues created by their code. But if a database abstraction framework built on top of JDBC can avoid SQL injection as much as possible in its API, all the better. From a SQL injection perspective, database abstraction frameworks can be divided into three categories:Simple utilities. These include Spring’s JdbcTemplate, or Apache’s DbUtils. They really just enhance the JDBC API with convenience (less exception handling, less verbosity, simpler variable binding, simpler data fetching). Of course, these tools won’t prevent SQL injection Full SQL abstraction. These include jOOQ, JaQu, QueryDSL, JPA’s CriteriaQuery and others. Their normal operation mode will always render bind values in generated SQL. This prevents SQL injection in most cases. The others. Many other frameworks (including ActiveJDBC and Hibernate) are mainly based on (SQL or HQL) string operations. While they abstract many SQL-related things, they do not prevent SQL injection at all.So, when you choose any SQL abstraction tool in your Java application, beware of the severity of SQL injection. And beware of the fact, whether your tool helps you prevent it or not! Reference: Database Abstraction and SQL Injection from our JCG partner Lukas Eder at the JAVA, SQL, AND JOOQ blog....

Stop Crapping on Start-Ups

Michael O. Church recently wrote a thought provoking blog post, “Don’t Waste Your Time in Crappy Startup Jobs“, and the author clearly put a lot of thought into writing the piece. Based on the comments and the retweets, it appears the article hit home for quite a few people. I think the article’s title might sway a reader’s interpretation a bit, or readers may simply see it as ‘Don’t Waste Your Time in a Startup’. I’m sure that wasn’t the intent of the article, but based on some of the comments, that sentiment seems to be the takeaway for many. The crux of the article is a list of seven misconceptions that the author chooses to dispel one by one. I’d like to take each of them and see if these are truly problems with start-ups, problems with the engineering industry, or even problems with expectations. (Mr. Church’s excerpts are in red, my comments follow) 1. A startup will make you rich. True, for founders, whose equity shares are measured in points. Not true for most employees, who are offered dimes or pennies.” First, I don’t think most engineers that join start-ups are expecting to get rich these days, and even founders aren’t all expecting to get rich. If you had written this in 1999, I’d agree this is a common misconception. Most employees in my experience see stock options or equity grants as ‘lottery tickets’, that they realize probably won’t pay off – but they also understand that you simply can’t win if you don’t play. “Moreover, raises and bonuses are very uncommon in startups. It’s typical for high performers to be making the same salary after 3 years as they earned when they started. (What happens to low performers, and to high performers who fail politically? They get fired, often with no warning or severance.) “ I don’t see bonuses or raises as uncommon in the start-ups I’ve worked with. My current client list includes a handful of start-ups that all offer bonus, and historically I’ve seen employees getting raises and bonuses from start-ups that are on par with some of my larger clients. And low performers being fired without warning or severance? Is that a start-up problem specifically? Low performers or people who ‘fail politically’ are fired in any sized company, the only difference may be severance. Again, this is not a ‘crappy start-up problem’. 2. The “actual” valuation is several times the official one.  “In truth, startup employees should value equity and options at about one-fourth the valuation that VCs will give it. If they’re giving up $25,000 per year in salary, they should only do so in exchange for $100,000 per year (at current valuation) in equity.” I usually advise candidates that they may want to weigh any equity simply as a chance to receive some additional compensation, and I’d generally advise them not to accept any offer that won’t afford them to live a lifestyle that makes them comfortable. If you can’t afford a 25K pay cut, don’t take one. 3. If you join a startup early, you’re a shoe-in for executive positions. Again, I just don’t think engineers are this naive today to believe this, or at least not the people I know. “Not so. In fact, one of the best ways not to get a leadership position in a startup is to be there early.” I’d love to see if any actual scientific evidence exists to back this claim up, but I wouldn’t know where to find it. For every engineer you can name that did not get a leadership spot, I’m sure someone else can name one that did. Again, in my experience I generally see that engineers who join early on are rewarded with leadership roles that they are qualified to do. Being the first or second engineering hire at a start-up doesn’t automatically give you the qualifications to be CTO, and if you expect you should be CTO/VP just because you were an early hire you probably need to rethink why you are joining the company. “Startups often involve, for engineers, very long hours, rapidly changing requirements, and tight deadlines, which means the quality of the code they write is generally very poor in comparison to what they’d be able to produce in saner conditions. It’s not that they’re bad at their jobs, but that it’s almost impossible to produce quality software under those kinds of deadlines.” True on hours, deadlines, requirements, and perhaps the code could be better in ideal conditions. I hear anecdotes all the time from engineers at large companies telling me how much free time they have with their highly reasonable deadlines and fully developed requirements being written in stone. Wait…no I don’t! Again, not a ‘crappy start-up problem’ – it’s the nature of the software game overall, just a bit amplified. “It may have been a heroic effort to build such a powerful system in so little time, but from an outside perspective, it becomes an embarrassment. It doesn’t make the case for a high-level position.” From an outside perspective, companies that may hire these engineers down the road will most likely respect the experience those engineers had in building the product under less than ideal conditions. Most hiring managers from outside firms won’t know whether the product was some epic flop anyway. “Once the company is rich and the social-climbing mentality (of always wanting “better” people) sets in, the programmers will be replaced with more experienced engineers brought in to ‘scale our infrastructure’… The old engineers probably won’t be fired, but they’ll be sidelined, and more and more people will be hired above them.” Well that was depressing. I’d say, more likely, once the product is built and the company can hire more engineers, the developers that were there in the beginning now have accomplished their goal and will make the choice to move on. The mentality of this type of engineer is to build something, but they may not want to maintain it. Once that excitement is gone for this type of engineer, they will go voluntarily. “Frankly put, being a J.A.P. (“Just A Programmer”) in a startup is usually a shitty deal. Unless the company makes unusual cultural efforts to respect engineering talent (as Google and Facebook have) it will devolve into the sort of place where people doing hard things (i.e. software engineers) get the blame and the people who are good at marketing themselves advance.” Is J.A.P. a great deal at other companies? There are plenty of established companies that don’t pay engineers great salaries, and work them long hours. I think the key point is the cultural efforts to respect engineering talent. My clients tend to love and respect their engineers, which is why I disagree with many of these stereotypes. 4. In startups, there’s no boss. This one’s patently absurd, but often repeated. Those who champion startups often say that one who goes and “works for a company” ends up slaving away for “a boss” or “working for The Man”, whereas startups are a path to autonomy and financial freedom.” No boss? I must admit, in my 15 years of tech recruiting I’ve never heard this one before. Who are these people that you are talking to? I’d say start-ups are a potential path to financial freedom, whereas working for an established company (with no ‘lottery tickets’) is probably not going to get you to early retirement. “People who really don’t want to have “a boss” should not be looking into VC-funded startups. There are great, ethical venture capitalists who wouldn’t go within a million miles of the extortive shenanigans I’ve described above. It’s probably true that most are. Even still, the power relationship between a founder and investor is far more lopsided than that between a typical employee and manager. No manager can legally disrupt an employee’s career outside of one firm; but venture capitalists can (and sometimes do) block people from being fundable.” How did we get from having ‘no boss’ to extortion by VC’s and managers? A manager disrupting an employee’s career outside of one firm??? WTF? Lemme guess...the author had a very bad experience? 5. Engineers at startups will be “changing the world”. With some exceptions, startups are generally not vehicles for world-changing visions. Startups need to think about earning revenue within the existing world, not ‘changing humanity as we know it’.” This might work on a small subset of 22 year old kids, but I think most people know they aren’t going to change the world. “…but people should understand that their chances of individually effecting global change, even at a startup, are very small.” The likelihood of ANYONE effecting global change is incredibly small at a start-up, and probably just as small at a large company. Again, this isn’t a ‘crappy start-up problem’. 6. If you work at a startup, you can be a founder next time around. Why not? No, seriously – why not? Working at a start-up doesn’t exclude you from being a founder next time, does it? “What I’ve said so far is that it’s usually a sh*tty deal to be an employee at a startup: you’re taking high risk and low compensation for a job that (probably) won’t make you rich, lead to an executive position, bring great autonomy, or change the world.” If you assume there is high risk and low compensation for every start-up job, I’d agree. Jobs with established companies don’t always pay well, rarely make you rich or lead to an exec position, and almost never allow you to change the world. If that is how you define a crappy job, all jobs are crappy. 7. You’ll learn more in a startup. This last one can be true; I disagree with the contention that it’s always true. Companies tend to regress to the mean as they get bigger, so the outliers on both sides are startups. And there are things that can be learned in the best small companies when they are small that can’t be learned anywhere else. In other words, there are learning opportunities that are very hard to come by outside of a startup.” So you won’t necessarily learn more in a start-up, but there are unique opportunities to learning in a start-up. This sounds like a feature, not a bug. Are there unique opportunities in larger companies to learn things that you can’t learn anywhere but in the larger company? Perhaps. “Startups are generally too busy fighting fires, marketing themselves, and expanding to have time to worry about whether their employees are learning.” Fighting fires is a great metaphor here. Do you know the best practice for fighting fires? It’s actually fighting fires. Of course, there is danger in that, but engineers learn much more by being in those environments than they do in a completely comfortable setting. It’s not about a company that can afford (both time and money) to send you to a training seminar, it’s about learning on the start-up job how to build something under tough conditions. CONCLUSION In conclusion, the problem with Mr. Church’s article isn’t that start-up jobs are crappy. It’s that the author feels that many people may have certain unrealistic expectations about start-up jobs. It assumes that all start-ups work you to death and pay you nothing, and that simply isn’t the case. It’s a stereotypical assumption, and it’s dangerous one. If you take any job and expect that you will absolutely: 1 – get rich 2 – become an executive 3 – have no boss 4 – change the world 5 – found a company within x years 6 – learn more than everyone else then I can assure you that you will be VERY disappointed, no matter the size or age of your new employer. I sense that people have more realistic expectations than Mr. Church gives them credit for, and the people I know in 2012 certainly do. A more appropriate title for his article would have been ‘Don’t Join a Start-Up with 1998 Expectations’. Reference: Stop Crapping on Start-Ups from our JCG partner Dave Fecak at the Job Tips For Geeks blog....

Java talking to iOS: Java objects to Apple plist serialization

I am happy to announce my first open source project java-plist-serializer that can help you with integrating Java and especially Spring based applications with iOS applications.  BackgroundI am working on project that has Java webapp as a backend and clients are iOS devices. Recently I’ve received task to create Web Service that returns plist – Property List data format used in iOS – as a response. Why plist and not JSON or classic XML? If you have to develop for iOS < 5.0 – there are no native classes to deserialize JSON. Property List format is supported by core iOS libraries so deserialization to NSDictionary is super fast and efficient.There are few plist – related libraries for Java but each of them requires to do a lot of manual work and rewrite Java objects step by step into Java equivalents of Apple NS* classes. I think nobody likes this kind of task. Thats why I have developed library for serializing Java objects into Plist in similar way to XStream XML serialization.   java-plist-serializer java-plist-serializer is an open source project hosted on Github that helps to develop communication between Java application and iOS application.does not depend on any XML related library customizable output thanks to @PlistIgnore, @PlistAlias and Naming Strategies thread safe – can be used as a singleton in project extensible – handlers for additional objects can be easily added Spring Framework integration provided by PlistViewUsage The heart of library is PlistSerializerImpl. In order to serialize obejcts to plist you have to create instance of PlistSerializerImpl and call one of serialization methods. For example: Input classes: public class Post { private String title; private Integer views = 0; private List<Comment> comments = new ArrayList<Comment>(); private Author author;public Post(Author author, String title, Integer views) { this.title = title; this.views = views; = author; } }public class Comment { private String content; private String author;public Comment(String author, String content) { this.content = content; = author; } }public class Author { private String name; }Objects of those classes are created and plistSerializer.toXmlPlist method is called Post post = new Post(new Author("jason bourne"), "java-plist-serializer introduction", 9); post.addComment(new Comment("maciejwalkowiak", "first comment")); post.addComment(new Comment("john doe", "second comment"));PlistSerializerImpl plistSerializer = new PlistSerializerImpl(); String xml = plistSerializer.toXmlPlist(post);xml variable will contain: <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>author</key> <dict> <key>name</key> <string>jason bourne</string> </dict> <key>comments</key> <array> <dict> <key>author</key> <string>maciejwalkowiak</string> <key>content</key> <string>first comment</string> </dict> <dict> <key>author</key> <string>john doe</string> <key>content</key> <string>second comment</string> </dict> </array> <key>title</key> <string>java-plist-serializer introduction</string> <key>views</key> <integer>9</integer> </dict> </plist>Spring Framework Integration In order to return plist as a response of Spring MVC controller you can use PlistView that extends AbstractView. There are several ways to configure Spring MVC. The easiest to understand example of usage of PlistView: @Controller public class BlogController { @RequestMapping(value = "/loadBlogPost", method = RequestMethod.GET) public ModelAndView loadBlogPost() { Post post = new Post(new Author("jason bourne"), "java-plist-serializer introduction", 9); post.addComment(new Comment("maciejwalkowiak", "first comment")); post.addComment(new Comment("john doe", "second comment"));ModelMap model = new ModelMap(); model.addAttribute("RESULT", notification);return new ModelAndView(new PlistView(), model); } }More detailed documentation can be found on project’s github page Conclusion Feel free to fork, extend. If you will find any issue please report them on github. Reference: Java talking to iOS: Java objects to Apple plist serialization from our JCG partner Maciej Walkowiak at the Software Development Journey blog....

IDE Project Files In Version Control – Yes or No? Of Course, Not!

Just recently I had some discussions with the clients who were claiming that they keep IDE project files in version control system hence they avoid any changes to those files. For reference, those are Eclipse generated .project and .classpath. From my point of view it is a bad practice by all means, however I usually prefer to collect some information on the topic before I say it loudly. So I asked from my G+ and Twitter followers, IDE project files in version control – Yes/No? Surprisingly, I’ve got quite a number of responses, so I decided to summarize the information as a blog post.  Basically, the answer to this question isn’t binary, yes or no, but it also could be ‘yes, but… ‘ or ‘no, if…’. So there might be some argument why someone prefers one way or another. The vast majority of the answers is ‘No, no, noooooooo!! Never!’. And just a couple of answers were ‘yes’ with some weak arguments of why someone should keep those files in version control. Here are some yes answers first. Bad stuff. Seems that the team isn’t really competent with the tools. The project should be easy to setup and why on earth I should press 100500 buttons to setup a project. If this is the case, the first thing that team lead should do, is to simplify the project structure, setup and build process. No excuses there. Yeah, yeah, I can already hear some arguments like ‘but we have a complex project’ or ‘this is the way our setup is done’. Bullsh*t!OK, there is some optimization for the setup, IDE specific though. If all the team members use the same setup, it might even make sense for those who want to keep hands off the console. Here’s another one:‘Specific Eclipse plugins’ – yeah! that’s is actually an argument for not keeping the files in version control! Eclipse plugins usually modify .project files as they add a ‘nature’ or any other project specific settings to the configuration. And actually, IntelliJ does the same, but (let me bash to tools a bit) IntelliJ can suggest the settings as you open a project from scratch. And with Eclipse, you have to do that manually. What if your colleague uses some awesome eclipse plugin that makes modifications to .project file, and you hate that plugin and do not want to install it, and the .project file is in version control? Here’s just a simple example that you could see while exporting a project with existing project files: This is so annoying to resolve this kind of problems. And all you want to do is just to open the project and proceed with your normal work. Here’s more:Currently, I use IntelliJ and the rest of the team uses Eclipse. And I absolutely do not care if they put the project files into version control, because I will import it into my IDE in two clicks anyway. So the assumption that ‘absolutely yes, given that the team is working with the same IDEs’ is wrong, and no viable argument here as well. However, here we have some much more interesting ideas:Wow, this is really interesting one – ‘those that define formatting or source code’. Indeed! In cases when you work on varions projects for different clients, the requirements and code styles might be quite different and it makes sense even to keep this kind of files in version control, so you can share it with the team and restore the code style settings if you lost them. Good point here! However, you can probably see the vector of my post now. So the point is, IDEs support Maven quite well, so why on earth I would need to keep the IDE settings in version control if we already have what we need: pom.xml. IntelliJ and NetBeans cope with that quite well, and Eclipse also, if you use JBoss Tools. But what if I’m a Maven hater? (I really am). Here’s an interesting conversation:Oh sure, Gradle that is! Well, the IDE support isn’t there yet. Luckily, STS provides a nice Gradle plugin for Eclipse, but the support for IntelliJ and NetBeans isn’t quite there yet. However, my claim is that Maven or Gradle isn’t the prerequisite to avoid the project files in version control. The real prerequisite is the simple setup of you project and a clean structure, so that importing the project is just a couple of clicks. Then you can cope with any kind of project, even if it doesn’t contain pom.xml. And here’s what most of them say about the topic: Myself, I have tried both ways – keeping the project files in version control and not checking them in, and my take is that under no circumstances it is a good idea to check the project files in. Again, a much better solution is to keep your project structure clean and simple, which might be harder than to check the files into version control, but much more beneficial on the long run. Thanks everyone for the input! Take care… Reference: IDE Project Files In Version Control – Yes or No? Of Course, Not! from our JCG partner Anton Arhipov at the Code Impossible blog....
Java Code Geeks and all content copyright © 2010-2015, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

Get ready to Rock!
To download the books, please verify your email address by following the instructions found on the email we just sent you.