I'm working on an application that requires the use of both JPA/Hibernate and RMI. Since RMI requires the use of a Security Policy to make sure that access to the network is correctly assigned I also now have to worry about the folder permissions.
I've been looking online (and here at SO) for a couple of days now trying to find a solution to this problem. Basically the problem is that for JPA/Hibernate to work I have to place the persistence.xml
file in the META-INF
directory, and the META-INF
directory must be under the src
directory of my project (which doesn't make sense to me either but it works). So that the project layout is basically:
org.project.root
|
|>src
| |
| |>org.project.package
| |
| |>META-INF
| |
| |>persistence.xml
|
|>config
|
|>database
|
|>logs
My security policy file I've been trying to grant read access to the folder ${user.dir}${/}src${/}META-INF${/}-
, however, when I try to run the application I get the error No Persistence provider for EntityManager named DERBY_ACPSTORE_CREATE
. My persistence.xml file however does contain this, and it works when comment out all the RMI stuff and stop reading the security policy. So my question is how can I get my security policy file to allow me to read the persistence.xml file?
UPDATE 1
Using the suggested path information from @Vineet Reynolds I'm able to see the file's path using:
File f = new File("META-INF/persistence.xml");
System.out.println(f.getAbsolutePath());
However, I'm still getting this error when I'm trying to create the database.
javax.persistence.PersistenceException: No Persistence provider for EntityManager named DERBY_ACPSTORE_CREATE
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:33)
at org.myproject.data.DBInit.dbInit(DBInit.java:29)
at org.myproject.ACPStoreMainService.main(ACPStoreMainService.java:91)
My persistence.xml as I said worked fine before I started using the security policy so I know that the persistence-unit "DERBY_ACPSTORE_CREATE" is present and correct.
Update 2
Although I'm not sure what good this is since it worked when I don't use the Security Policy here's my persistence.xml contents:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="DERBY_ACPSTORE_CREATE">
<provider>org.hibernate.ejb.HibernatePersistence</provider
<class>org.myproject.data.MessageHistory</class>
<properties>
<property name="hibernate.connection.driver_class"
value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
<property name="hibernate.connection.url" value="jdbc:derby:database/acpstore;create=true" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="use_sql_comments" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.connection.username" value="user" />
<property name="hibernate.connection.password" value="password" />
</properties>
</persistence-unit>
</persistence>
UPDATE 3
As I mentioned in the comment to the answer from Vineet Reynolds below I've tested the persistence.xml without the security and it is now working. Then when I reinstate the security policy then I get the errors again. As such below is the contents of my security policy and how I create the security in my application:
grant {
permission java.lang.RuntimePermission "shutdownHooks";
permission java.lang.RuntimePermission "readFileDescriptor";
permission java.lang.RuntimePermission "writeFileDescriptor";
permission java.util.PropertyPermission "user.dir", "read";
permission java.net.SocketPermission "172.10.10.21:1024-65535", "connect, accept, resolve";
permission java.net.SocketPermission "172.10.10.21:1-1023", "connect,resolve";
permission java.io.FilePermission "${user.dir}${/}META-INF${/}-", "read";
permission java.io.FilePermission "${user.dir}${/}config${/}-", "read, write, delete";
permission java.io.FilePermission "${user.dir}${/}database${/}-", "read, write, delete";
};
And this is what happens in my application to set the security manager
if(System.getSecurityManager() == null)
{
System.setSecurityManager(new RMISecurityManager());
}
UPDATE 4
I've found a message that I didn't notice before coming from log4j. The message is
[main] INFO org.hibernate.ejb.Ejb3Configuration - Could not find any META-INF/persistence.xml file in the classpath
which seems odd to me. So I listed the directories in the classpath and I found org.project.root\bin
but not org.project.root
. I know now that the META-INF in the runtime is located as org.project.root\META-INF
, and that the classpath should point to the org.project.root
so that JPA and hibernate can access find the persistence.xml. So would could it be that I need to somehow change the classpath to match this?
I'll give Vineet a up vote for helping me with knowing where the META-INF folder ends up, however, I finally figured out what my permissions problem is.
The java.io.FilePermission
is hierarchical, meaning you have to give "read" access to higher folders before you can give it to lower directories.
Basically in my security policy file I should have done permission java.io.FilePermission "${user.dir}${/}-", "read";
first before I entered permission java.io.FilePermission "${user.dir}${/}META-INF${/}-", "read";