Creating a Custom Repository

This example shows how to create a custom repository. First create a class that implements the Repository interface.

          public class MyXmlRepository implements Repository {

              private String myProp;

              public String getMyProp() {
                  return myProp;
              }

              public void load(InputStream inputStream, Hashtable properties) throws IOException {
                  KXmlParser parser = new KXmlParser();
                  try {
                      parser.setInput(inputStream, null);
                  } catch (XmlPullParserException e) {
                     throw new IOException(e.toString());
                  }
                  try {
                      parser.nextTag();
                      parser.require(XmlPullParser.START_TAG, null, "test-app");
                      while(parser.nextTag() == XmlPullParser.START_TAG) {
                          parser.require(XmlPullParser.START_TAG, null, "myprop");
                          myProp = parser.nextText();
                      }
                  } catch (XmlPullParserException e) {
                      throw new IOException(e.toString());
                  }
              }
          }
            

Using information from the registry-config, the RepositoryRegistry will handle reading the file off of the file system (or within the jar) and passing it to your class as an InputStream. You can do anything you want with the InputStream. In this case, we pass the stream into a KXmlParser and proceed to parse the tags.

All you need to use this file is to invoke:

MyXmlRepository repository = (MyXmlRepository) repositoryRegistry.find("my-xml");

after loading the RepositoryRegistry with your config file. To see a working example, check the test classes within the build.

Creating a Custom Registry Loader

Registry-CDC comes with a standard registry-config.xml format. You may, however, tailor the format of the registry-config.xml file to your specific needs. This example shows how to create and use a custom registry loader. First you will need to create a class that implements the RegistryLoader interface. The following code is taken from the org.jvending.registry.impl.StandardRegistryLoader class and reads in the default registry-config.xml.

    public void load(InputStream inputStream) throws IOException {

        KXmlParser parser = new KXmlParser();
        try {
            parser.setInput(inputStream, null);
        } catch (XmlPullParserException e) {
            throw new IOException(e.toString());
        }
        try {
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "registry-config");
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "repositories");

            while (parser.nextTag() == XmlPullParser.START_TAG) {
                parser.require(XmlPullParser.START_TAG, null, "repository");
                repositories.add(getRepositoryObject(parser));
            }
        } catch (XmlPullParserException e) {
            throw new IOException(e.toString());
        }
        loadIntoRegistry();
    }

    public Hashtable getRepositories() {
        return repoMap;
    }
                

The purpose of the load method is to take the config information and generate Repository classes, stored within the repoMap. In the case above, the loadIntoRegistry method takes the RepositoryObjects that are in the repositories List, instantiates them and adds them to the repoMap.

After implementing the class, go to the registries.properties file within the jar. You will see something like:

    registryLoader=org.jvending.registry.impl.StandardRegistryLoader
                

Change the repositoryLoader value to your class. If you are building from scratch, this file is located in registry/src/main/resources. The build will automatically place it within the jar. Note that you will need either to disable the unit tests in the testregistry package, since they depend on the standard loader, or to compile directly from the registry module.

If you don't want to recompile the registry-cdc, you can set the RegistryyLoader programatically:

    repositoryRegistry.setRegistryLoader(new MyRegistryLoader());
                

Creating a Custom Repository Loader

There may be a case when you want to retain the format of the registry-config.xml but you want the repository to load the resources in a different way than that provided by the StandardRepositoryLoader. This example shows how to create and use a custom repository loader. First you will need to create a class that implements the RepositoryLoader interface. The following code is taken from the org.jvending.registry.impl.StandardRepositoryLoader class.

public Repository loadRepository(String fileUri, String repositoryClass, Hashtable initParams) throws IOException {
    Hashtable props = (initParams != null) ? initParams : new Hashtable();

    if (fileUri == null || fileUri.trim().equals("")) throw new IOException("File uri must be provided.");
    if (repositoryClass == null || repositoryClass.trim().equals(""))
        throw new IOException("Repository class name must be provided: File Name = " + fileUri
                + ", Properties = " + props.toString());

    InputStream stream = null;
    Repository repository = null;
    try {
        stream = new FileInputStream(fileUri);
    } catch (IOException e) {
        stream = this.getClass().getResourceAsStream(fileUri);
    }
    String message = "File Name = " + fileUri +
            ", Repository Class = " + repositoryClass + ", Properties = " + props.toString();

    if (stream == null)
        throw new IOException("Unable to loadRegistry config file: " + message);

    try {
        Class c = Class.forName(repositoryClass);
        repository = (Repository) c.newInstance();
        repository.load(stream, props);
    } catch (IOException e) {
        throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
    } catch (Exception e) {
        throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
    } catch (Error e) {
        throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
    }
    return repository;
}
                

Now lets say that we want to replace the loader with one that will load the repositories within a ServletContext (This is an actual example of what will be released within the upcoming registry-j2ee). As you can see below, we are loading the repository from the ServletContext

        public class ServletRepositoryLoader implements RepositoryLoader {

            private ServletContext servletContext;

            private static Logger logger = Logger.getLogger("ServletRepositoryLoader");

            public ServletRepositoryLoader(ServletContext servletContext) {
                this.servletContext = servletContext;
            }

            /**
             *
             * @param fileUri a URL, file system path or war file
             * @param repositoryClass
             * @param initParams
             * @return
             * @throws IOException
             */
            public Repository loadRepository(String fileUri, String repositoryClass, Hashtable initParams) throws IOException {
                Hashtable props = (initParams != null) ? initParams : new Hashtable();

                if (fileUri == null || fileUri.trim().equals("")) throw new IOException("File uri must be provided.");
                if (repositoryClass == null || repositoryClass.trim().equals(""))
                    throw new IOException("Repository class name must be provided: File Name = " + fileUri
                            + ", Properties = " + props.toString());

                Repository repository = null;

                InputStream inputStream = servletContext.getResourceAsStream(fileUri);
                    if(inputStream == null) {
                        logger.severe("Could not find " + fileUri);
                        throw new IOException("Could not find " + fileUri);
                    }

                String message = "File Name = " + fileUri +
                        ", Repository Class = " + repositoryClass + ", Properties = " + props.toString();

                try {
                    Class c = Class.forName(repositoryClass);
                    repository = (Repository) c.newInstance();
                    repository.load(inputStream, props);
                } catch (IOException e) {
                    throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
                } catch (Exception e) {
                    throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
                } catch (Error e) {
                    throw new IOException("JV-REG-001:" + e.toString() + " : " + message);
                }
                return repository;
            }

            public String getLoaderName() {
                return this.getClass().getName();
            }
        }


    

After implementing the class, go to the registries.properties file within the jar. You will see something like:

    repositoryLoader=org.jvending.registry.impl.StandardRepositoryLoader
                

Change the repositoryLoader value to your class, which in this case is org.jvending.registry.ServletRepositoryLoader .Similar to the RegistryLoader example, you can, instead, set the RepositoryLoader programatically:

    repositoryRegistry.setRepositoryLoader(new MyRepositoryLoader());