Just two small classes I wrote to be able to do some easy validation when you need to have more contextual information when validating an entity. This will allow you to do that easily while preventing the rewriting of boilerplate code.
The annotation:
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Repeatable;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target({TYPE})
@Retention(RUNTIME)
@Repeatable(Predicate.List.class)
@Constraint(validatedBy = PredicateValidator.class)
@Documented
public @interface Predicate {
String message() default "{predicate.invalid}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String name();
@Target({TYPE})
@Retention(RUNTIME)
@Documented
public @interface List {
Predicate[] value();
}
} |
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Repeatable;
import javax.validation.Constraint;
import javax.validation.Payload;
@Target({TYPE})
@Retention(RUNTIME)
@Repeatable(Predicate.List.class)
@Constraint(validatedBy = PredicateValidator.class)
@Documented
public @interface Predicate {
String message() default "{predicate.invalid}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String name();
@Target({TYPE})
@Retention(RUNTIME)
@Documented
public @interface List {
Predicate[] value();
}
}
The validator:
import java.util.HashMap;
import java.util.Map;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PredicateValidator implements ConstraintValidator<Predicate, Object> {
private static final Map<String, java.util.function.Predicate> PREDICATES = new HashMap<>();
private java.util.function.Predicate predicate;
@Override
public void initialize(Predicate predicate) {
if (!PREDICATES.containsKey(predicate.name())) {
throw new IllegalArgumentException("No predicate with name " + predicate.name() + " found");
}
this.predicate = PREDICATES.get(predicate.name());
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return predicate.test(value);
}
public static void addPredicate(String name, java.util.function.Predicate p) {
PREDICATES.put(name, p);
}
} |
import java.util.HashMap;
import java.util.Map;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PredicateValidator implements ConstraintValidator<Predicate, Object> {
private static final Map<String, java.util.function.Predicate> PREDICATES = new HashMap<>();
private java.util.function.Predicate predicate;
@Override
public void initialize(Predicate predicate) {
if (!PREDICATES.containsKey(predicate.name())) {
throw new IllegalArgumentException("No predicate with name " + predicate.name() + " found");
}
this.predicate = PREDICATES.get(predicate.name());
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return predicate.test(value);
}
public static void addPredicate(String name, java.util.function.Predicate p) {
PREDICATES.put(name, p);
}
}
And a small example:
import java.util.Objects;
@Predicate(name = "myPredicate")
@Predicate(name = "myPredicate2")
public class Pojo {
static {
PredicateValidator.addPredicate("myPredicate", obj -> {
Pojo p = (Pojo) obj;
System.out.println("Test 1");
return Objects.equals(p.getValueOne(), p.getValueTwo());
});
PredicateValidator.addPredicate("myPredicate2", obj -> {
Pojo p = (Pojo) obj;
System.out.println("Test 2");
return Objects.equals(p.getValueOne(), p.getValueTwo());
});
}
private String valueOne;
private String valueTwo;
public String getValueOne() {
return valueOne;
}
public void setValueOne(String valueOne) {
this.valueOne = valueOne;
}
public String getValueTwo() {
return valueTwo;
}
public void setValueTwo(String valueTwo) {
this.valueTwo = valueTwo;
}
} |
import java.util.Objects;
@Predicate(name = "myPredicate")
@Predicate(name = "myPredicate2")
public class Pojo {
static {
PredicateValidator.addPredicate("myPredicate", obj -> {
Pojo p = (Pojo) obj;
System.out.println("Test 1");
return Objects.equals(p.getValueOne(), p.getValueTwo());
});
PredicateValidator.addPredicate("myPredicate2", obj -> {
Pojo p = (Pojo) obj;
System.out.println("Test 2");
return Objects.equals(p.getValueOne(), p.getValueTwo());
});
}
private String valueOne;
private String valueTwo;
public String getValueOne() {
return valueOne;
}
public void setValueOne(String valueOne) {
this.valueOne = valueOne;
}
public String getValueTwo() {
return valueTwo;
}
public void setValueTwo(String valueTwo) {
this.valueTwo = valueTwo;
}
}
Creating new classes during runtime can be nice when you need it. Below is a small example of what is possible. (No interface or existing base class is used in this example so reflection is required to invoke a method)
ClassPool classPool = ClassPool.getDefault();
CtClass cc = classPool.makeClass("AwesomeNewClass");
cc.addMethod(CtMethod.make("public String getValue() { return \"Hello World!\"; }", cc));
Class awesome = cc.toClass();
Object o = awesome.newInstance();
Method method = awesome.getMethod("getValue");
String returnValue = (String) method.invoke(o); |
ClassPool classPool = ClassPool.getDefault();
CtClass cc = classPool.makeClass("AwesomeNewClass");
cc.addMethod(CtMethod.make("public String getValue() { return \"Hello World!\"; }", cc));
Class awesome = cc.toClass();
Object o = awesome.newInstance();
Method method = awesome.getMethod("getValue");
String returnValue = (String) method.invoke(o);
1. Download the jackrabbit jca from http://jackrabbit.apache.org/downloads.html
2. Deploy it on glassfish
3. Create a new Resource Adapter Configuration (Create a new Thread-pool first if you want)
4. Create a new Connector Connection Pool with the new Resource Adapter Configuration
Add the following properties:
homeDir <full path to where your repository is located>
configFile <full path to where your repository config (repository.xml) is located>
5. Create the connector resource and name it 'jcr/repository' for example. |
1. Download the jackrabbit jca from http://jackrabbit.apache.org/downloads.html
2. Deploy it on glassfish
3. Create a new Resource Adapter Configuration (Create a new Thread-pool first if you want)
4. Create a new Connector Connection Pool with the new Resource Adapter Configuration
Add the following properties:
homeDir <full path to where your repository is located>
configFile <full path to where your repository config (repository.xml) is located>
5. Create the connector resource and name it 'jcr/repository' for example.
You can now access your repository in the code. Below is a sample.
package com.famvdploeg.jackrabbit;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
/**
*
* @author wytze
*/
@Stateless
public class JackrabbitManager {
@Resource(mappedName="jcr/repository", type=javax.jcr.Repository.class)
private Repository repository;
public String getFromRepo() {
try {
Session session = repository.login(new SimpleCredentials("username", "password".toCharArray()));
Node root = session.getRootNode();
Node hello = root.addNode("hello");
hello.setProperty("message", "Hello, World!");
session.save();
// Retrieve content
Node node = root.getNode("hello");
System.out.println(node.getPath());
System.out.println(node.getProperty("message").getString());
root.getNode("hello").remove();
return "Created and removed!";
} catch (Exception ex) {
return ex.getMessage();
}
}
} |
package com.famvdploeg.jackrabbit;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
/**
*
* @author wytze
*/
@Stateless
public class JackrabbitManager {
@Resource(mappedName="jcr/repository", type=javax.jcr.Repository.class)
private Repository repository;
public String getFromRepo() {
try {
Session session = repository.login(new SimpleCredentials("username", "password".toCharArray()));
Node root = session.getRootNode();
Node hello = root.addNode("hello");
hello.setProperty("message", "Hello, World!");
session.save();
// Retrieve content
Node node = root.getNode("hello");
System.out.println(node.getPath());
System.out.println(node.getProperty("message").getString());
root.getNode("hello").remove();
return "Created and removed!";
} catch (Exception ex) {
return ex.getMessage();
}
}
}
A possible Java EE 6 Servlet which you can use for WebDAV support. You will need jackrabbit-jcr-server for the base servlet. You can get it by building the source package with maven.
package com.famvdploeg.jackrabbit;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.jcr.Repository;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebInitParam;
/**
*
* @author wytze
*/
@WebServlet(
name = "webdav",
urlPatterns = "/repository/*",
initParams = {
@WebInitParam(name = "resource-path-prefix", value = "/repository"),
@WebInitParam(name = "missing-auth-mapping", value = "admin:admin"),
@WebInitParam(name = "resource-config", value = "/WEB-INF/config.xml")
}
)
public class SimpleWebdavServlet extends org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet {
@EJB
private RepositoryFactory repositoryFactory;
private Repository repository;
@PostConstruct
public void postConstruct() {
repository = repositoryFactory.getRepository();
}
@Override
public Repository getRepository() {
return repository;
}
} |
package com.famvdploeg.jackrabbit;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.jcr.Repository;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebInitParam;
/**
*
* @author wytze
*/
@WebServlet(
name = "webdav",
urlPatterns = "/repository/*",
initParams = {
@WebInitParam(name = "resource-path-prefix", value = "/repository"),
@WebInitParam(name = "missing-auth-mapping", value = "admin:admin"),
@WebInitParam(name = "resource-config", value = "/WEB-INF/config.xml")
}
)
public class SimpleWebdavServlet extends org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet {
@EJB
private RepositoryFactory repositoryFactory;
private Repository repository;
@PostConstruct
public void postConstruct() {
repository = repositoryFactory.getRepository();
}
@Override
public Repository getRepository() {
return repository;
}
}
Possible extended configuration of the repository:
<!-- Store all items larger than 256 bytes in the FileDataStore -->
<DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
<param name="path" value="${rep.home}/repository/datastore"/>
<param name="minRecordLength" value="256"/>
</DataStore> |
<!-- Store all items larger than 256 bytes in the FileDataStore -->
<DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
<param name="path" value="${rep.home}/repository/datastore"/>
<param name="minRecordLength" value="256"/>
</DataStore>
I ran out of brain capacity. So here is a list of commands to do some basic glassfish stuff.
Updating: |
pkg image-update |
Start domain: |
asadmin start-domain |
Stop domain: |
asadmin stop-domain |
Deploy item: |
asadmin deploy <path to file> |
List JNDI entries: |
asadmin list-jndi-entries |