Using Apache Sling adaptTo API

Apache Sling provides a way to adpat Sling related classes to our domain classes. The Resource and ResourceResolver interface provides the adaptTo method, which adapts the objects to other classes.Examples of the usage of this API would be when we want to get the JCR Node instance from the current Resource object. The API documentation can be found here.In this post we will change our contact list application a bit to use the adaptTo API.Creating Our First AdapterThe first thing we are going to do is to create our model class, Contact. It basically will contain the attributes of our contact model. It will be a simple POJO:public class Contact { private String name; private String email; private String phone; private String address; private String contactImage; //..getters and setters } Now in order to be able to adapt Resource objects to our Contact class we need to create an AdapterFactory. The adapter factories are registered as OSGI services. For that we need to implement the AdpaterFactory interface and the method getAdapter. The AdapterFactory have two key properties that should be defined:adaptables: An array of the classes that can adapted to other classes defined in the adapters propertyadapters: An array of the classes that can be adapted from the classes defined in the adaptables propertyIn our example we will create an AdpaterFactory that will make us able to adapt an instance of Resource class to our Contact class.We can see it below:@Component @Service public class ContactAdapterFactory implements AdapterFactory{ @Property(name="adapters") public static final String[] ADAPTER_CLASSES = { Contact.class.getName() }; @Property(name="adaptables") public static final String[] ADAPTABLE_CLASSES = { Resource.class.getName() }; @Override @SuppressWarnings("unchecked") public AdapterType getAdapter(Object adaptable, Class type) { if(adaptable instanceof Resource && type.equals(Contact.class)) { Contact contact = new Contact(); Resource resource = (Resource)adaptable; ValueMap valueMap = ResourceUtil.getValueMap((Resource)adaptable); contact.setName(valueMap.get("name", String.class)); contact.setEmail(valueMap.get("email", String.class)); contact.setPhone(valueMap.get("phone", String.class)); contact.setAddress(valueMap.get("address", String.class)); Resource contactImage = resource.getChild("contactImage"); if(contactImage != null) { contact.setContactImage(contactImage.getPath()); } System.out.println(contact); return (AdapterType)contact; } else { return null; } } }Let’s explain it a bit:We can see the adapters and adaptables properties being set below:@Property(name="adapters") public static final String[] ADAPTER_CLASSES = { Contact.class.getName() }; @Property(name="adaptables") public static final String[] ADAPTABLE_CLASSES = { Resource.class.getName() };As we could see we’ve set the adaptables to Resource class and the adapters to Contact class.Then the next step is the getAdapter method which is responsible to create an instance of the adapter class from the adaptable instance. We can see it below:public AdapterType getAdapter(Object adaptable, Class type) { if(adaptable instanceof Resource && type.equals(Contact.class)) { Contact contact = new Contact(); Resource resource = (Resource)adaptable; ValueMap valueMap = ResourceUtil.getValueMap((Resource)adaptable); contact.setName(valueMap.get("name", String.class)); contact.setEmail(valueMap.get("email", String.class)); contact.setPhone(valueMap.get("phone", String.class)); contact.setAddress(valueMap.get("address", String.class)); Resource contactImage = resource.getChild("contactImage"); if(contactImage != null) { contact.setContactImage(contactImage.getPath()); } return (AdapterType)contact; } else { return null; } }It receives two arguments; adaptable, which is the instance of the Adaptable class, and type, the class we are going to adapt to. Basically we check if the adaptable is instance of our expected adaptable class and if the type matches our expected adapter class. If so, we create our Contact instance and set its properties with the resource properties.Now if we deploy our OSGI bundle, we can see our adapter registered in the Apache Felix Web Console on Sling -> Sling Adapters section:Now we can change our JSP to use our adapter, so we can adapt our contact nodes to the Contact class. We can see the changed part of the JSP below: 

  • ${contactProps.name}
    ${contactProps.name}
    ${contactProps.address}
    ${contactProps.phone}
    ${contactProps.email}
  • The main change is that instead of adapting to ValueMap class we are adapting to our Contact class:Then we can acces our POJO attributes using the JSP Expression Language.The JSP became a little bit cleaner but we can make it a bit better.As we can see, we still need to get the the contacts node using the taglib and to adapt each contact node to our contact class. Let’s make it a bit better. Let’s create another AdapterFactory that will return us the complete Contact list so we do not need to use all those taglibs.For this, we will create another POJO, ContactList:public class ContactList { private List contacts = new ArrayList(); //... getters and setters public void addContact(Contact contact) { this.contacts.add(contact); } } Now our AdapterFactory will have as adaptable SlingHttpServletRequest and as adapter ContactList. We can see it below:@Component @Service public class ContactListAdapterFactory implements AdapterFactory{ @Property(name="adapters") public static final String[] ADAPTER_CLASSES = { ContactList.class.getName() }; @Property(name="adaptables") public static final String[] ADAPTABLE_CLASSES = { SlingHttpServletRequest.class.getName() }; public static String CONTACTS_NODE = "contacts"; @Override @SuppressWarnings("unchecked") public AdapterType getAdapter(Object adaptable, Class type) { if(adaptable instanceof SlingHttpServletRequest && type.equals(ContactList.class)) { ContactList contactList = new ContactList(); SlingHttpServletRequest request = (SlingHttpServletRequest)adaptable; Resource appResource = request.getResource(); Resource contactsNode = appResource.getChild(CONTACTS_NODE); Iterable contacts = contactsNode.getChildren(); Iterator contactsIterator = contacts.iterator(); while(contactsIterator.hasNext()) { contactList.addContact(contactsIterator.next().adaptTo(Contact.class)); } return (AdapterType)contactList; } return null; } }This is very similar to our ContactAdapterFactory, but now adapting from SlingHttpServletRequest class. Basically we get the contacts node than its children. Also we can see our first AdapterFactory in action when we make:contactsIterator.next().adaptTo(Contact.class) After we deploy our OSGI bundle with our new adapter factory we can see it registered in the Web Console:Now we can rewrite our JSP to be like below: 
    • ${contact.name}
      ${contact.name}
      ${contact.address}
      ${contact.phone}
      ${contact.email}
    Now we just need to adapt the slingRequet to our ContactList and use the JSTL core tags to iterate over the contacts and print display their properties using EL.ConclusionWith the adaptTo API we can convert the Sling related objects to our Model objects by using the AdapterFactory classes. By checking the Sling Adapters console we can see that is used a lot in the Apache Sling framework.The complete source code is my github repo in a new branch adapt_to.In order to deploy the code you just need:git clone https://github.com/fjunior87/sling-contact-list.git cd sling-contact-list git checkout adapt_to mvn clean install -P autoInstallBundleAnd access the application.That’s it for today, I hope you enjoyed it.Thanks and see you in the next post.

    Read more

    U.S. to auction $1.6 million of bitcoin from various cases

    NEW YORK The U.S. government said on Monday it plans to auction over 2,700 bitcoins that were forfeited during several cases, several of which stemmed from investigations of the online black market known as Silk Road.The U.S. Marshals Service said that the online auction would be held on Aug. 22, and that potential bidders must register by Aug. 18. The bitcoin are worth about $1.6 million, according to the Bitstamp exchange.The auction is the latest by the Marshals Service of the digital currency. It completed four prior auctions from June 2014 to November 2015 of bitcoins seized during the prosecution of Ross Ulbricht, who authorities say ran Silk Road.His case is one of nine criminal, civil or administrative matters from which the Marshals Service said the 2,719 bitcoins had been forfeited and are subject to the latest auction. Ulbricht, 32, was sentenced in May 2015 to life in prison after being convicted for orchestrating a scheme that enabled more than $200 million of anonymous online drug sales through Silk Road using bitcoin. He is appealing.Only about 2.8 bitcoins in the latest auction came from Ulbricht's case, the Marshals Service said. The bulk of the bitcoins in the auction, 1,294, came from a civil forfeiture case related to a Silk Road drug dealer, Matthew Gillum, who was sentenced in 2015 to nine years in prison, the Marshals Service said.It said another 65 bitcoins came from the case of Carl Force, a former U.S. Drug Enforcement Administration agent who was sentenced in October to 78 months in prison for stealing bitcoins during the Silk Road investigation. The agency said another 664 bitcoins came from the case of Sean Roberson, a Florida man who prosecutors said created an online shop for selling counterfeit credit and debit cards. He was sentenced in November 2015 to 78 months in prison. (Reporting by Nate Raymond in New York; Editing by Bernadette Baum and Frances Kerry)

    Read more

    Study finds cosmic rays increased heart risks among Apollo astronauts

    CAPE CANAVERAL, Fla. Apollo astronauts who ventured to the moon are at five times greater risk of dying from heart disease than shuttle astronauts, U.S. researchers said on Thursday, citing the dangers of cosmic radiation beyond the Earth's magnetic field. The study by researchers at Florida State University and NASA found that three Apollo astronauts, including Neil Armstrong, the first person to walk on the moon, or 43 percent of those studied, died from cardiovascular disease, a finding with implications for future human travel beyond Earth.The research, published in the journal Scientific Reports, was the first to look at the mortality of Apollo astronauts, the only people so far to travel beyond a few hundred miles (km) of Earth.It found that the chief health threat to the Apollo astronauts came from cosmic rays, which are more prevalent and powerful beyond the magnetic bubble that surrounds Earth.NASA disputed the findings, saying it was too early to draw conclusions about the effect of cosmic rays on Apollo astronauts because the current data is limited. The results of the study have implications for the United States and other countries, as well as private companies, such as Elon Musk’s SpaceX, which are planning missions to Mars and other destinations beyond Earth.For the study, the researchers examined the death records of 42 astronauts who flew in space, including seven Apollo veterans, and 35 astronauts who died without ever going into space.They found the Apollo astronauts’ mortality rate from cardiovascular disease was as much as five times higher than for astronauts who never flew, or for those who flew low-altitude missions aboard the space shuttle that orbited a few hundred miles above Earth. A companion study simulated weightlessness and radiation exposure in mice and showed that radiation exposure was far more threatening to the cardiovascular system than other factors, lead scientist Michael Delp said in an interview."What the mouse data show is that deep space radiation is harmful to vascular health," he said. So far, only 24 astronauts have flown beyond Earth’s protective magnetic shield, in missions spanning a four-year period from December 1968 to December 1972.Of those, eight have died, seven of whom were included in the study. The cause of death of the eighth astronaut, Apollo 14's Edgar Mitchell, who died in February 2016, has not been released, so he was excluded from the study, Delp said. Mitchell was the sixth person to walk on the moon.Delp and colleagues are working on a follow-up study that includes more detail on family medical histories, smoking and other factors. (Reporting by Irene Klotz; Editing by Julie Steenhuysen and Peter Cooney)

    Read more

    Solar-powered plane circles globe, returns to UAE

    ABU DHABI A solar-powered aircraft successfully completed the first fuel-free flight around the world on Tuesday, returning to Abu Dhabi after an epic 16-month voyage and demonstrating the potential of renewable energy.The plane, Solar Impulse 2, touched down in the United Arab Emirates capital at 0005 GMT (0405 local time) on Tuesday. It first took off from Abu Dhabi on March 9, 2015, beginning a landmark journey of about 40,000 km (24,500 miles) around the globe and nearly 500 hours of flying. Unfavorable weather at times hindered smooth flying, causing the plane to be grounded for months in some countries. Swiss explorers Bertrand Piccard and André Borschberg, Solar Impulse founders and pilots, took turns piloting the aircraft with a wingspan larger than a Boeing 747 and weighing only as much as a family car. The Swiss team is campaigning to bolster support for clean energy. The propeller-driven aircraft's four engines are powered exclusively by energy collected from more than 17,000 solar cells built the plane's wings. Excess energy is stored in four batteries during daylight hours to keep the plane flying after dark.Over its entire mission, Solar Impulse 2 cruised at altitudes of up to 9,000 meters and at an average speed of between 45 and 90 km (12.5 and 25 miles) per hour. The plane had 16 stopovers along the way including in Oman, India, Myanmar, China, Japan, the United States, Spain and Egypt. Abu Dhabi’s green energy firm Masdar is the official host partner of Solar Impulse 2. Oil-rich Abu Dhabi is investing billions in industry, tourism and renewables to diversify its economy away from oil. (Reporting by Stanley Carvalho, editing by Sami Aboudi and Hugh Lawson)

    Read more

    SpaceX rocket lifts off on cargo run, then lands at launch site

    CAPE CANAVERAL, Fla. An unmanned SpaceX rocket blasted off from Florida early on Monday to send a cargo ship to the International Space Station, then turned around and landed itself back at the launch site.The 23-story-tall Falcon 9 rocket, built and flown by Elon Musk’s Space Exploration Technologies, or SpaceX, lifted off from Cape Canaveral Air Force Station at 12:45 a.m. EDT (0445 GMT).Perched on top of the rocket was a Dragon capsule filled with nearly 5,000 pounds (2,268 kg) of food, supplies and equipment, including a miniature DNA sequencer, the first to fly in space.Also aboard the capsule was a metal docking ring of diameter 7.8 feet (2.4 m), that will be attached to the station, letting commercial spaceships under development by SpaceX and Boeing Co. ferry astronauts to the station, a $100-billion laboratory that flies about 250 miles (400 km) above Earth. The manned craft are scheduled to begin test flights next year.Since NASA retired its fleet of space shuttles five years ago, the United States has depended on Russia to ferry astronauts to and from the station, at a cost of more than $70 million per person.As the Dragon cargo ship began its two-day journey to the station, the main section of the Falcon 9 booster rocket separated and flew itself back to the ground, touching down a few miles south of its seaside launch pad, accompanied by a pair of sonic booms. "Good launch, good landing, Dragon is on its way," said NASA mission commentator George Diller.Owned and operated by Musk, the technology entrepreneur who founded Tesla Motors Inc, SpaceX is developing rockets that can be refurbished and re-used, potentially slashing launch costs. With Monday’s touchdown, SpaceX has successfully landed Falcon rockets on the ground twice and on an ocean platform during three of its last four attempts.SpaceX intends to launch one of its recovered rockets as early as this autumn, said Hans Koenigsmann, the firm's vice president for mission assurance. (Reporting by Irene Klotz, Editing by Chris Michaud and Clarence Fernandez)

    Read more
    Older Post