File storage under Wicket using Apache Jackrabbit


2009-12-04 23:32 | Author: vytautas.racelis

Apache Jackrabbit is a fully conforming implementation of the Content Repository for Java Technology API. We will discuss how to integrate Apache Jackrabbit as file repository into Apache Wicket in this article.

You should be familiar with Apache Jackrabbit before start using it :)

Features

- Simple usage;
- Different types of file storage (database, file system).

Apache Jackrabbit install

You should download Apache Jackrabbit from official site, or may use maven dependency:

<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-core</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-commons</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>1.0</version>
</dependency>

File repository implementation

After jars installed into eclipse we may start develop file repository: create, search, retrieve, delete files (and maybe something else). For example:

String uuid = null;
try {
Session session = contentSessionFacade.getDefaultSession();
Node rootNode = session.getRootNode();

Node folder = (rootNode.hasNode(path))?
rootNode.getNode(path):createFolder (session, path, rootNode);
Node file = folder.addNode(name, "nt:file");
Node fileContent = file.addNode ("jcr:content", "nt:resource");
fileContent.addMixin("mix:referenceable");
fileContent.setProperty ("jcr:mimeType", mimeType);
fileContent.setProperty ("jcr:lastModified", Calendar.getInstance());
fileContent.setProperty("jcr:data", fileStream);
session.save();
uuid = fileContent.getUUID();
} catch (Exception e) {
throw new FileStorageException ("Error while storing file", e);
}
return uuid;

This part is usage of JCR, so i will not follow further.

Repository manager

Repository manager initializes and destroys repository. It also provides factory to get JCR Session:
- WebApplication.init () should invoke repository manager's init method to create Jackrabbit repository;
- WebApplication.onDestroy () should invoke repository manager's shutdown methdod to shutdown Jackrabbit repository; - WebApplication.getJCRSessionFactory () should return JCR session factory (see below).

Session Factory

JCR's session is not thread safe, so responsibility of Session Factory would be to return correct instance of javax.jcr.Session. One of solutions is to use ThreadLocal:

ThreadLocal<Map<String, Session>> container = 
new ThreadLocal<Map<String, Session>>() {
@Override
protected Map<String, Session> initialValue() {
return new HashMap<String, Session>();
}
};

public Session getSession(String workspace) {
final Map<String, Session> map = container.get();
Session session = map.get(workspace);
if (session != null && !session.isLive()) {
session = null;
}
if (session == null) {
try {
final Credentials credentials = getCredentials();
session = getRepository().login(credentials, workspace);
} catch (Exception e) {
throw new JcrSessionException(workspace, e);
}
map.put(workspace, session);
container.set(map);
}
return session;
}

Caution: Working with the same folder in multiuser environment may cause inconsistent state of JCR session, so there is your responsibility to ensure correct work of javax.jcr.Session (e.g., every user should work under it's own folder, synchronized method of file storage, etc.)

Extended WebRequestCycle

You should cleanup ThreadLocal container when sessions are not used anymore. One of places might be extenstion of org.apache.wicket.protocol.http.WebRequestCycle

public abstract class ContentWebRequestCycle extends WebRequestCycle {
public ContentWebRequestCycle(WebApplication application,
WebRequest request, Response response) {
super(application, request, response);
}

@Override
protected void onEndRequest() {
if (getContentSessionFactory () != null) {
getContentSessionFactory ().cleanup();
}
}

protected abstract SessionFactory getContentSessionFactory ();

}

And then you should override your web application's method newRequestCycle:

@Override
public RequestCycle newRequestCycle(Request request, Response response) {
return new ContentWebRequestCycle(this, (WebRequest) request, response) {
@Override
protected SessionFactory getContentSessionFactory() {
return repositoryManager.getContentSessionFactory ();
}
};
}

Combine all together

Result might be found under demo section

 

Remember: this is just an abstract article how to create file repository under Wicket :)

 
 
 
 
 
 
 
<< < > >>
 
About xaloon.org

xaloon.org provides apache wicket based components for web and business solutions.

Learn more »
Follow Us (RSS)
Help & Support

Contact us in order to get help and support.

Online contact form »
Get in touch
Online contact form »