Houdini


Source link: https://github.com/vbauer/houdini

Houdini

No performer should attempt to bite off red-hot iron unless he has a good set of teeth.

Houdini is a simple and humane type conversion system, which allows you to prevent a lot of unnecessary code.

For example, when you work with Spring Type Conversion API, you have to implement each converter as a separate class. It produces a lot of excessive code. Houdini allows you to aggregate different converters in a single place and re-use common logic without additional classes.

The project was named in honor of Harry Houdini (born Erik Weisz, later Ehrich Weiss or Harry Weiss) who was a Hungarian-American illusionist and stunt performer, noted for his sensational escape acts.

See an Example section for a quick start.

Online documentation:

Main features

Comparison with other conversion systems

Usually, each big project with some conversion system (ex. Spring's Converters) has the following problems:

A huge number of converter classes
Houdini allows to join several converters into a single bean (unlike Spring converters), so it will minimize the number of classes and prevent unnecessary code. For example, you can join converters by functionality or by modules. It also simplifies source code navigation for developer. An additional feature is that the smaller class number of classes also decreases compilation time a little bit.

Duplicated code in converters
Some converters could be very similar to other (except filling of some fields). Using Spring it is most likely to see basic classes or shared components to resolve this situation. Using Houdini it is unnecessary to create additional classes, you can just put this logic in a new method.

Conditional converters
It is a typical situation for REST services:

  • sometimes it is necessary to send full information,
  • sometimes short information,
  • or need to combine it somehow using conditionals.

Using Spring converters you need to create new POJO and new converters to resolve it. Houdini allows to use additional conditional parameters. (See an Example section).

Out of IOC context
This is a rare case for JEE developers (and typical case for others), but sometimes it's necessary to use some converters without something like ConversionService. It could be needed when our code is out of Spring context (ex: shared code for Spring and GWT apps). Using Houdini we could put all needed converters into a single bean and use it like a simple Java class.

Setup

Maven

<repository>
  <id>jitpack.io</id>
  <url>https://jitpack.io</url> </repository>  <dependency>
  <groupId>com.github.vbauer</groupId>
  <artifactId>houdini</artifactId>
  <version>1.4.2</version> </dependency>

Gradle

repositories {

  maven {

url "https://jitpack.io"
  
}
 
}
 dependencies {

  compile 'com.github.vbauer:houdini:1.4.2' 
}

Configuration

To work with Houdini's magic, you have 2 basic interfaces and corresponding implementations:

  • ObjectConverterRegistry (ObjectConverterRegistryImpl) is needed to store and search converters.
  • ObjectConverterService (ObjectConverterServiceImpl) allows to convert some data to another data.

Reminder:

Houdini isn't dependent on third-party dependencies, but it has extra integration with Spring and Guice frameworks. Of course, it can be used with pure Java or Android projects.

Java / Android configuration

How to configure Houdini with pure Java:

// Create registry service to store converters: final ObjectConverterRegistry registry = new ObjectConverterRegistryImpl();
  // After that you can specify all needed converters: // registry.registerConverters(new UserConverter());
 // registry.registerConverters(new RoleConverter());
 // registry.registerConverters(new CompanyConverter());
  // Create service which makes conversions (it could be a simple singleton object): final ObjectConverterService converterService = new ObjectConverterServiceImpl(registry);

You can also use default registry object with ObjectConverterService, 1LOC:

final ObjectConverterService converterService = new ObjectConverterServiceImpl();

Guice / RoboGuice configuration

Houdini contains the specific Guice module to support converters ( com.github.vbauer.houdini.ext.guice.ObjectConverterModule):

final Injector injector = Guice.createInjector(new ObjectConverterModule());

Now, all your beans will be checked for converters and all found converters will be registered. ObjectConverterModule module also defines 2 beans: ObjectConverterRegistry and ObjectConverterService.

Spring configuration

Houdini has a good integration with Spring framework. Just choose the most appropriate way how to configure it:

  • Configure application context using Java code
  • Use XML file to configure context

Java based configuration

You need to configure 2 beans:

  • ObjectConverterService which you will use to convert objects
  • and ObjectConverterBeanPostProcessor which is necessary to detect converters in the Spring context
@Configuration public class AppContext {

  @Bean
  public ObjectConverterService objectConverterService() {

return new ObjectConverterServiceImpl();

  
}

  @Bean
  public ObjectConverterBeanPostProcessor objectConverterBeanPostProcessor() {

return new ObjectConverterBeanPostProcessor(objectConverterService());

  
}
 
}

You also need to define converter beans in the AppContext or using @ComponentScan annotation.

XML Schema-based configuration

You still need to configure the same 2 beans:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation=" 

  http://www.springframework.org/schema/beans 

  http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- Converter service bean -->
  <bean class="com.github.vbauer.houdini.service.ObjectConverterServiceImpl" />

<!-- Bean post processor to register converters  -->
  <bean class="com.github.vbauer.houdini.ext.spring.ObjectConverterBeanPostProcessor" /> </beans>

Spring Boot support

Houdini has out of the box integration with Spring Boot. You do not need to define ObjectConverterService and ObjectConverterBeanPostProcessor in your application context. Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.

See ObjectConverterConfiguration for more details.

Conversion API

To make new converter, you need to create a new class (or use an existing one) and mark this bean as converter using @ObjectConverter annotation.

It is possible to add this annotation on:

  • Bean class - all public methods from this class will be registered as converters.
  • Bean's public method - only this method will be registered as converter.

All necessary converters will be registered in bean ObjectConverterService. This service also provides all necessary methods for data conversion:

  • Register converter methods.
  • Convert some data object (with parameters) to another data object.
  • Convert Set or List of data to Set/ List of data.
  • Convert Set/ List of data to one element or Set/ List (it could be useful for some REST API services).

That's all!

Example

This tiny example shows the power of Houdini: one class, two converters, re-usable logic, no one line of excessive code.

// Use also @Component annotation in case of Spring framework. @ObjectConverter public class UserConverter {

public UserDTO shortInfo(final User user) {

return fullInfo(user, false);

  
}

public UserDTO fullInfo(final User user, Boolean full) {

final UserDTO userDTO = new UserDTO()

 .setId(user.getId())

 .setLogin(user.getLogin());

 if (Boolean.TRUE.equals(full)) {

 userDTO.setPassword(user.getPassword());

}

 return userDTO;
  
}
  
}

Converting User domain object to DTO:

final User user = new User()
  .setId(ID)
  .setLogin(LOGIN)
  .setPassword(PASSWORD)  final UserDTO shortUserDTO1 = converterService.convert(UserDTO.class, user);
 final UserDTO shortUserDTO2 = converterService.convert(UserDTO.class, user, false);
 final UserDTO fullUserDTO = converterService.convert(UserDTO.class, user, true);

Development

To build project in strict mode with tests, you can run:

mvn -P strict clean package

Might also like

  • jconditions - Extra conditional annotations for JUnit.
  • jackdaw - Java Annotation Processor which allows to simplify development.
  • herald - Logging annotation for Spring framework.
  • caesar - Library that allows to create async beans from sync beans.
  • commons-vfs2-cifs - SMB/CIFS provider for Commons VFS.
  • avconv4java - Java interface to avconv tool.

License

Copyright 2015 Vladislav Bauer

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Resources

A multi level menu view (like WeChat subscription Accounts) library for Android.

This beautiful and easy to use library will help to add Lollipop Material Design SearchView in your project.

A simple, easy to use, no frills, form validator for Android.

This plugin makes it easy to search text in strings resources.

An RxJava 2 CallAdapter.Factory implementation for Retrofit 2.

Usb serial controller for Android.

Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes