Casting collections in Java
Assuming two classes A and B as
class A {}
class B extends A {}
It is just logical that casting B to A works fine:
A anObjectOfClassA = new B();
But when it comes to collections of As and Bs, a strange phenomenon appears in Java:
Collection<B> collectionOfBs = new LinkedList<B>(); Collection<A> collectionOfAs = (Collection<A>)collectionOfBs; // this line does not compile!
That is, though the collection wrapper (the java.util.Collection class) is the same and B extends A, casting a collection of objects of class B to a collection of objects of class A throws an compile-time error.
But it works using generics (the whole class for the sake of completeness and reusability):
import java.util.Collection;
import java.util.LinkedList;
public class CollectionCastingExample {
class A {}
class B extends A {}
Collection<B> collectionOfBs = new LinkedList<B>();
// Collection<A> collectionOfAs = (Collection<A>)collectionOfBs;
Collection<A> collectionOfAs = downCastCollection(collectionOfBs, A.class);
/**
* Casts a collection of objects of class B where B extends A to a collection of objects of class A.
*
* @param <T> Base class
* @param collection Collection of objects of a class extending T
* @param aClass Representation of T
* @return Collection of objects of T casted from given collection of objects of a class extending T.
*/
@SuppressWarnings("unchecked")
public static <T> Collection<T> downCastCollection(Collection<? extends T> collection,
Class<T> aClass) {
return (Collection<T>) collection;
}
}
Despite the fact that a @SuppressWarnings("unchecked") is required, it avoids iterating over the whole collection of Bs and casting each of them from B to A plus adding them to a new collection of As.
Adding a New Service (GWT)
Adding a new servlet/service to you GWT application is quite straight forward, e.g. by copying the example “greetingService” or creating a new servlet. But it’s easy to overlook a required change/adjustment of your project’s configuration and you might end up with an error message like “Blocked attempt to access interface ‘some.package.SomeService’, which is not implemented by ‘some.other.package.SomeOtherServiceImpl’; this is either misconfiguration or a hack attempt”.
Check list (some should be replaced with whatever you want to call your new service):
- Copy or create files:
SomeService.java and SomeServiceAsync.java in client package
SomeServiceImpl.java in server package + change implementation statement to SomeService - Adjust web.xml:
<servlet> <servlet-name>someServlet</servlet-name> <servlet-class>some.package.SomeServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>someServlet</servlet-name> <url-pattern>/[copy base directory name from other service declaration]/some</url-pattern> </servlet-mapping>
- Annotate interface SomeService.java:
@RemoteServiceRelativePath("some") - Connect to your new service in the client:
private final SomeServiceAsync someService = GWT.create(SomeService.class);
Definitely some possibilities to make a mistakes or miss something here.