That's very nifty, Norman. This is a simultaneously inspiring and depressing reminder that despite having used Tapestry since version 3, I still feel like a total noob. :-) I'd love to see a blog series on "Services you never knew about and fun things to do with them!"
Michael On 15 August 2012 18:33, Norman Franke <nor...@myasd.com> wrote: > Something similar was asked in another thread, but I figured others may > find this helpful. > > I wanted to automatically bind my interfaces and implementations of my > numerous DAOs in my AppModule. It's pretty easy, so here is what I idd. > This is called from the bind static method. Obviously you'd need to change > the package names. My naming convention is to put the implementation > packages in a sub ".impl" package, e.g. com.myasd.db.dao.impl in my case. > Classes then are suffixed with "Impl" to make Eclipse's package > auto-complete suggestions work better. I've been using this for a few > years, at lest. > > @SuppressWarnings({ "unchecked", "rawtypes" }) > static void bindDAOs(ServiceBinder binder) { > try { > ClassLoader contextClassLoader = > Thread.currentThread().getContextClassLoader(); > List<Class<?>> daos = > PackageEnumerator.getClassesForPackage("com.myasd.db.dao"); > for (Class<?> dao : daos) { > String pkg = dao.getPackage().getName(); > String cls = dao.getSimpleName(); > try { > Class impl = > contextClassLoader.loadClass(pkg+".impl."+cls+"Impl"); > binder.bind(dao, impl).scope(ScopeConstants.PERTHREAD); > } catch (ClassNotFoundException e) { > // Ignore, we just won't bind that class. > } > } > } catch (ClassNotFoundException e) { > e.printStackTrace(); > } > } > > > Helper method borrowed from who-knows-where: > > public static List<Class<?>> getClassesForPackage(String packageName) > throws ClassNotFoundException { > // This will hold a list of directories matching the pckgname. > // There may be more than one if a package is split over multiple > // jars/paths > List<Class<?>> classes = new ArrayList<Class<?>>(); > ArrayList<File> directories = new ArrayList<File>(); > try { > ClassLoader cld = > Thread.currentThread().getContextClassLoader(); > if (cld == null) { > throw new ClassNotFoundException("Can't get class > loader."); > } > // Ask for all resources for the path > Enumeration<URL> resources = > cld.getResources(packageName.replace('.', '/')); > while (resources.hasMoreElements()) { > URL res = resources.nextElement(); > if (res.getProtocol().equalsIgnoreCase("jar")) { > JarURLConnection conn = (JarURLConnection) > res.openConnection(); > JarFile jar = conn.getJarFile(); > for (JarEntry e : Collections.list(jar.entries())) { > > if > (e.getName().startsWith(packageName.replace('.', '/')) && > e.getName().endsWith(".class") > && !e.getName().contains("$")) { > String className = e.getName().replace("/", > ".").substring(0, e.getName().length() - 6); > System.out.println(className); > classes.add(Class.forName(className)); > } > } > } else > directories.add(new > File(URLDecoder.decode(res.getPath(), "UTF-8"))); > } > } catch (NullPointerException x) { > throw new ClassNotFoundException(packageName + " does not > appear to be " > + "a valid package (Null pointer exception)"); > } catch (UnsupportedEncodingException encex) { > throw new ClassNotFoundException(packageName + " does not > appear to be " > + "a valid package (Unsupported encoding)"); > } catch (IOException ioex) { > throw new ClassNotFoundException("IOException was thrown when > trying " + "to get all resources for " > + packageName); > } > > // For every directory identified capture all the .class files > for (File directory : directories) { > if (directory.exists()) { > // Get the list of the files contained in the package > String[] files = directory.list(); > for (String file : files) { > // we are only interested in .class files > if (file.endsWith(".class")) { > // removes the .class extension > classes.add(Class.forName(packageName + '.' + > file.substring(0, file.length() - 6))); > } > } > } else { > throw new ClassNotFoundException(packageName + " (" + > directory.getPath() > + ") does not appear to be a valid package"); > } > } > return classes; > } > > Norman Franke > Answering Service for Directors, Inc. > www.myasd.com > > > >