I like clean simple condensed code, esecially when it comes to tests. I really do not like seeding the lists this way
List<String> values = new ArrayList<String>();
values.add("test");
values.add("foo");
values.add("bar");
bean.setValues(values);
This method requires a lot of keyboard interaction if you do not use your mouse. Having to navigate lines of code with a keyboard can interrupt ones flow. Or you can use the mouse to highlight, copy and paste but who likes touching their mouse when coding.
So i started intializing my list like this for quite some time.
List<String> values = new ArrayList<String>(){{
add("test");
add("foo");
add("bar");
}};
bean.setValues(values);
If you are not familier with double brace initializers then this code can be difficult to read and even can seem invalid to some. But this solved the problem by reducing my keyboard interaction so I used it.
Just recently I started using this method.
String[] values = {"test", "foo", "bar"};
bean.setValues(Arrays.asList(values));
This really solved my problem with reducing my keyboard interaction even more than before and it also made the code easy to read and condensed.
I am not a big fan of .NET Web Forms, and as a Java developer I am fortunate to never be forced to work with it. Well this was true until I was asked to make code changes to a JSF application at work. JSF and Web Forms are both event driven web frameworks that store user state on the page. When a click on the page occurs it submits the users previous state and calls the event mapped to the click that was made on the page. The idea of both are to create a web page that interacts like a native desktop application, with the exception of the lengthy and obvious page refresh between clicks. The idea behind Web Forms when it was released was to take the large pool of Microsoft desktop developers and easily transition to web developers. From what I have read about JSF, it was modeled after component architecture of AWT. The only difference is that I would say there is not as large of a pool of Java GUI developers as Microsoft had. Most of the time you will hear me talk up Java and its frameworks in comparison to Microsoft; when comparing event driven frameworks I am going to say that Microsoft wins simply for the development experience. This most likely has a lot to do with Visual Studio and the framework being developed together as a pair where Java develops these items as isolated projects.
When we first started unit testing our EJB3 Stateless Session beans we ran into the problem on how to inject mocked objects into objects that were under test. There were a couple of techniques that attempted such as adding setters, which we didn't like because there was no way to prevent someone from calling them during production. The second option was to create a constructor with all the dependencies which solved the setter problem but this would require a lot more work since some beans could have ten or more dependencies.
The solution that worked best for us was inject the beans manually using refection. I built a small utility class to accomplish this and had evolved overtime to what it is today.
import java.lang.reflect.Field;
public class BeanUtil {
/**
* Attempts to inject a dependency into a object that doesn't have setter
* methods or constructors to do so. This will search for the first field
* that matches the dependency type.
*
* @param bean
* The object that needs a dependency injected into
* @param dependency
* The object that fulfills the required dependency
* @throws NoSuchFieldException
*/
public static void inject(Object bean, Object dependency)
throws NoSuchFieldException {
// since no field name was given we will look for the field via type
Field[] fields = bean.getClass().getDeclaredFields();
String fieldName = null;
for (Field field : fields) {
if (field.getType().isInstance(dependency)) {
fieldName = field.getName();
break;
}
}
// check to make sure we found a field
if (fieldName == null) {
throw new NoSuchFieldError("Unable to locate a field in "
+ bean.getClass().getName() + " that is an instance of "
+ dependency.getClass().getName());
}
inject(bean, dependency, fieldName);
}
/**
* Attempts to inject a dependency into a object that doesn't have setter
* methods or constructors to do so. This method should be used when you
* have two fields of the same type.
*
* @param bean
* The object that needs a dependency injected into
* @param dependency
* The object that fulfills the required dependency
* @param fieldName
* Name of the field that the dependency should be injected to.
* @throws NoSuchFieldException
*/
public static void inject(Object bean, Object dependency, String fieldName)
throws NoSuchFieldException {
// find filed and inject dependency
Field field = bean.getClass().getDeclaredField(fieldName);
boolean accessible = field.isAccessible();
field.setAccessible(true);
try {
field.set(bean, dependency);
} catch (IllegalAccessException e) {
throw new RuntimeException("Should not happen since we changed "
+ "the accessibility of the object to public", e);
}
field.setAccessible(accessible);
}
/**
* Attempts to inject a dependencies into a object that doesn't have setter
* methods or constructors to do so. This will search for the first field
* that matches the dependency type.
*
* @param bean
* The object that needs a dependency injected into
* @param dependencies
* Objects that fulfills the required dependencies
* @throws NoSuchFieldException
*/
public static void inject(Object bean, Object... dependencies)
throws NoSuchFieldException {
for (Object dependency : dependencies) {
inject(bean, dependency);
}
}
}
Then to use it you can either static import the BeanUtil class or just call BeanUtil.inject()
Java 1.3 introduced some handy new classes java.lang.reflect.Proxy and the java.lang.reflect.InvocationHandler; basically this allows you to dynamically create a proxy class that implements given set of interfaces and wrap this proxy class around a concret implementation of the class. It works by implementing the InvocationHandler interface which is called by the proxy prior to calling the wrapped class. Your implementation of the InvocationHandler can then choose to invoke the wrapped class, throw an exception, call another class, or anything else you may want it to do. At first it does not seem apparent why this is needed but they real power comes in building generic frameworks such as Hibernate and EJB3 application servers where offen times you are working with proxies instead of concreate implementations.
Recently I was asked to create a functional test to call a set of three web services for every member in our system. This was driven by the fact that we are integrating to a new system and there is a large data migration effort that is currently underway; the steak holders found it to be crucial that every member was migrated properly. The first thing that came to mind was how to deal with the large dataset, just under two million members, but the problems with dealing with datasets of this size have mostly been solved. So with no real problems facing me I was simple going to build a few very large loops and let the test run; but then I started to think about reusability.
Today we are calling three methods for all members, what about running one method on all accounts, or we can run all the plan methods against all our promocodes that have a free trial period. Since these are all plausible tests in not only production but within dev as well I wanted to make this as reusable and helpful as possible. Currently we have all our functional test calling web services clients that were generated by using JAX-WS. We have a ServiceFactory class that is used to create all web service clients for our functional test. So if you can wrap a proxy around these web services you can then monitor and record any method call you like in detail.
To start out I first I created a Recorder interface that would provide the contract on how record a service call.
public interface Recorder {
public void record(Method method, Object[] params, Object returned);
public void record(Method method, Object[] params, Throwable thrown);
}
Since we are only wanting to track a few service calls and not all the methods the service provides I created an abstract class for connivence.
abstract public class AbstractRecorder implements Recorder {
List<Method> recordingMethods = new ArrayList<Method>();
public void add(Method method) {
recordingMethods.add(method);
}
public void add(Class clazz, String method, Class... params)
throws SecurityException, NoSuchMethodException {
add(clazz.getMethod(method, params));
}
public void add(Class clazz) {
for (Method method : clazz.getMethods()) {
recordingMethods.add(method);
}
}
public boolean isRecording(Method method) {
return recordingMethods.contains(method);
}
}
Now that we have a contract for recording methods we can now implement the InvocationHandler interface and fulfill the contact for the proxy.
public class ServiceInvocationHandler<I> implements InvocationHandler {
private final Recorder recorder;
private final I service;
private ServiceInvocationHandler(I service, Recorder recorder) {
this.service = service;
this.recorder = recorder;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returned;
try {
returned = method.invoke(service, args);
} catch (Throwable t) {
recorder.record(method, args, t);
throw t;
}
recorder.record(method, args, returned);
return returned;
}
public static <I> I createInvocationHandler(I service, Recorder recorder) {
InvocationHandler hanlder = new ServiceInvocationHandler<I>(service, recorder);
return (I) Proxy.newProxyInstance(service.getClass().getClassLoader(),
new Class[] { service.getClass() }, hanlder);
}
}
The object stores an instance of the concert class that is being wrapped and an instance of the recorder that will be used to record the service call. We will use the createInvocationHandler method to create proxy that wraps the service and also to create the InvocationHandler. When creating the proxy using newProxyInstance the first parameter is the classloader for the proxy. The second parameter is and array of interfaces you want the proxy to intercept, this means you can only intercept and wrap public methods since interfaces can only have public methods. The third paramater is the concreate class you would like to wrap.
For the most part I am ready to use my proxy. I can simply create a new service using my ServiceFactory and call createInvocationHandler which will wrap the service. But I wanted to place another layer of abstraction on creating the recordable service so any developer that needs to record service calls need to simple create a class that implements Recorder.
public class ServiceRecorderFactory {
private final Recorder recorder;
public ServiceRecorderFactory(Recorder recorder) {
this.recorder = recorder;
}
public <I> I get(I serviceInterface) {
I service = ServiceFactory.get(serviceInterface);
return ServiceInvocationHandler.createInvocationHandler(service, recorder);
}
}
When creating a ServiceRecorderFactory they would simply provide the Recorder you implemented and then they can request services just like before. It will simply call the normal ServiceFactory to create the service, create a proxy that wraps the service, then returns the proxy. Here is an example of it in use.
public class TestMember {
public static void main(String[] args) {
JdbcRecorder recorder = new JdbcRecorder();
recorder.add(MemberService.class, "getMember", Long.class);
ServiceRecorderFactory serviceFactory = new ServiceRecorderFactory(recorder);
MemberService memberService = serviceFactory.get(MemberService.class);
Long[] members = new Long[]{1L, 2L, 4L, 5L, 6L};
for(Long memberId : members){
memberService.getMember(memberId); //will record
memberService.getAddress(memberId); //will not record
}
}
}