I'm trying to use Apache Shiro (v1.2) in a JavaEE6 web application on a GlassFish v3.1.2 application server.
In GlassFish I've set up a datasource (jdbc/myds) which I have tested to work through JPA2.
I would like to use the same datasource for authenticating users using the Shiro JDBC realm.
I've got the following in shiro.ini:
# DataSource config
ds = org.apache.shiro.jndi.JndiObjectFactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = jdbc/myds
# JDBC realm config
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = false
jdbcRealm.authenticationQuery = SELECT password FROM user_account WHERE email = ?
jdbcRealm.userRolesQuery = SELECT role_name FROM user_group_membership WHERE email = ?
jdbcRealm.dataSource = $ds
When I deploy the application I get the following Exception (summarised):
FINE: Encountered object reference '$ds'. Looking up object with id 'ds'
FINEST: Applying property [dataSource] value [org.apache.shiro.jndi.JndiObjectFactory#2ca061] on object of type [org.apache.shiro.realm.jdbc.JdbcRealm]
SEVERE: Unable to start Filter: [Unable to set property 'dataSource' with value [$ds] on object of type org.apache.shiro.realm.jdbc.JdbcRealm. If '$ds' is a reference to another (previously defined) object, prefix it with '$' to indicate that the referenced object should be used as the actual value. For example, $$ds].
org.apache.shiro.config.ConfigurationException: Unable to set property 'dataSource' with value [$ds] on object of type org.apache.shiro.realm.jdbc.JdbcRealm. If '$ds' is a reference to another (previously defined) object, prefix it with '$' to indicate that the referenced object should be used as the actual value. For example, $$ds
at org.apache.shiro.config.ReflectionBuilder.applyProperty(ReflectionBuilder.java:373)
at org.apache.shiro.config.ReflectionBuilder.applySingleProperty(ReflectionBuilder.java:198)
at org.apache.shiro.config.ReflectionBuilder.applyProperty(ReflectionBuilder.java:159)
at org.apache.shiro.config.ReflectionBuilder.buildObjects(ReflectionBuilder.java:119)
...
...
Caused by: java.lang.IllegalArgumentException: Cannot invokeorg.apache.shiro.realm.jdbc.JdbcRealm.setDataSource on bean class 'class org.apache.shiro.realm.jdbc.JdbcRealm' - argument type mismatch - had objects of type "org.apache.shiro.jndi.JndiObjectFactory" but expected signature "javax.sql.DataSource"
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2235)
at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2151)
at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1957)
...
If instead I define an actual MySQL data source it works fine, e.g.
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = localhost
ds.user = root
ds.password = root
ds.databaseName = mydb
Any help is much appreciated.
This looks like it is likely a classpath issue. The stack trace references line numbers for ReflectionBuilder that make sense in shiro 1.1.0. However, they don't make sense in shiro 1.2.0. However, since JndiObjectFactory is new in shiro 1.2.0, and both classes are in shiro-core, it seems likely that you have both jars on the classpath.
You should first look in your war file, make sure that both jars aren't in there. If they are, you can fix your war file by removing the 1.1.0 version. If not, I would begin looking to see if you are inheriting an old version of shiro through the glassfish infrastructure somehow.
Related
I am using Weblogic 12c and I have configured my datasources like this:
Notice that they are all deployed on target "AdminServer". Also, the "Name" field and "JNDI Name" field are identical. For example, suppose one datasource's name is "MYDS".
Now, when I try to acquire that datasource through Spring Data JPA like this:
#Bean
#Primary
public DataSource businessDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean();
dataSource.setResourceRef(true);
dataSource.setJndiName("MYDS");
dataSource.afterPropertiesSet();
return (DataSource) dataSource.getObject();
}
I get the following error when trying to deploy the war file to weblogic:
Bean instantiation via factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [javax.sql.DataSource]: Factory method
'businessDataSource' threw exception; nested exception is
javax.naming.NameNotFoundException: Unable to resolve 'MYDS'. Resolved
''; remaining name 'MYDS'
Also I see this error:
DEBUG o.s.jndi.JndiObjectFactoryBean - Converted JNDI name
[java:comp/env/MYDS] not found - trying original name [MYDS].
javax.naming.NameNotFoundException: While trying to look up
comp/env/MYDS in /app/myapp/webclient/404708050.; remaining name
'comp/env/MYDS'
Just looking at the source for setResourceRef and it states :
public void setResourceRef(boolean resourceRef)
Set whether the lookup occurs in a Java EE container,
i.e. if the prefix "java:comp/env/" needs to be added if the JNDI name doesn't already contain it.
Default is "false".
Note: Will only get applied if no other scheme (e.g. "java:") is given.
If you are setting it to true have you tried adding java:comp/env/ to the JNDI name ?
I'm trying to run an application using a Datasource on JBOSS EAP 6.4
In the standalone.xml file my data source is well defined.
When I try a :
Context context = new InitialContext();
NamingEnumeration<NameClassPair> list = context.list("");
while (list.hasMore())
{
String name = list.next().getName();
System.out.println(name);
}
I only get TransactionManager while I'm expecting as well my data source named in the standalone.xml as jndi-name="java:jboss/datasources/OracleDS".
Why my datasource is not defined in the jndi environnement? Am I missing some configuration?
The Context.list(Name) does not include subcontexts. In other words you cannot iterate through all the registered names using context.list(""). If you want to list the data sources you'd need to use context.list("java:jboss/datasources).
The reason you only get the /TransactionManager is because it's the only one defined under the root namespace.
I am trying to access a Datasource specified in the Tomcat server.xml and context.xml by
play.
The playapplication is located as war within the tomcat webapps and also has the Connection in its web.xml specified with:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/Testconnection</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
To see hat the connection is specified I used a jsp to check the configuration:
Context initialContext = new InitialContext();
Context componentBindings = (Context) initialContext.lookup("java:comp/env");
DataSource dataSource = (DataSource) componentBindings.lookup("jdbc/Testconnection");
Connection connection = dataSource.getConnection();
String connectionUrl = connection.getMetaData().getURL();
out.println(connectionUrl);
This showed the exspected result.
When trying to access the database within the play application it always results in:
"could not find datasource for ....: Token not allowed in path expression: '-'" pointing to the line containing DB.withConnection in my play app.
So what is confusing me is that there is not such a token as '-' within my whole code.
I tried to access the following combinations:
DB.withConnection("java:comp/env/jdbc/Testconnection") { imlicit c => .......}
DB.withConnection("java:jdbc/Testconnection") { imlicit c => .......}
DB.withConnection("jdbc/Testconnection") { imlicit c => .......}
Would be great if anybody can provide me with a solution or point me in the right direction.
Thank you very much!
Solution:
So the Solution (thanks to applicius!) could be:
import javax.naming.{Context, InitialContext}
import javax.sql.DataSource
[...]
var conn: java.sql.Connection = (new InitialContext).lookup("java:/comp/env").asInstanceOf[Context].lookup("jdbc/Testconnection").asInstanceOf[DataSource].getConnection
val result: Option[Result] = SQL(queryName).on(("variable","replaceValue")).singleOpt(Result.rowMapper)(conn)
[...]
Play DB API is expecting a Play datasource name (one corresponding to entry in Play application.conf), not a JNDI name.
Either you get connection by your self using regular JNDI lookup and use it in your Play app (having to release it by yourself), or you move/duplicate datasource settings into Play config.
Although there already are quite some StackOverflow questions, blog entries, etc. on the web, I still cannot figure out a solution to the problem stated below.
Similar to this question (Injecting EJB within JAX-RS resource on JBoss7) I'd like to inject a EJB instance into a JAX-RS class. I tried with JBoss 5, JBoss 7, and WildFly 8. I either get no injection at all (field is null), or the server does not deploy (as soon as I try to combine all sorts of annotations).
Adding #Stateless to the JAX-RS makes the application server know both classes as beans. However, no injection takes place.
Is there a way to inject EJBs into a REST application? What kind of information (in addition to that contained in the question linked to above) could I provide to help?
EDIT: I created a Github project showing code that works (with Glassfish 4.0) and does not work (with JBoss 5).
https://github.com/C-Otto/beantest
Commit 4bf2f3d23f49d106a435f068ed9b30701bbedc9d works using Glassfish
4.0.
Commit 50d137674e55e1ceb512fe0029b9555ff7c2ec21 uses Jersey 1.8, which does not work.
Commit 86004b7fb6263d66bda7dd302f2d2a714ff3b939
uses Jersey 2.6, which also does not work.
EDIT2:
Running the Code which I tried on JBoss 5 on Glassfish 4.0 gives:
Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
EDIT3: The crucial information might be that I'd like a solution that works on JBoss 5
If you don't want to make your JAX-RS resource an EJB too (#Stateless) and then use #EJB or #Resource to inject it, you can always go with JNDI lookup (I tend to write a "ServiceLocator" class that gets a service via its class.
A nice resource to read about the topic:
https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project
A sample code:
try {
// 1. Retreive the Home Interface using a JNDI Lookup
// Retrieve the initial context for JNDI. // No properties needed when local
Context context = new InitialContext();
// Retrieve the home interface using a JNDI lookup using
// the java:comp/env bean environment variable // specified in web.xml
helloHome = (HelloLocalHome) context.lookup("java:comp/env/ejb/HelloBean");
//2. Narrow the returned object to be an HelloHome object. // Since the client is local, cast it to the correct object type.
//3. Create the local Hello bean instance, return the reference
hello = (HelloLocal)helloHome.create();
} catch(NamingException e) {
} catch(CreateException e) {
}
This is not "injecting" per-se, but you don't use "new" as-well, and you let the application server give you an instance which is managed.
I hope this was useful and I'm not telling you something you already know!
EDIT:
This is an excellent example: https://docs.jboss.org/author/display/AS72/EJB+invocations+from+a+remote+client+using+JNDI
EDIT 2:
As you stated in your comment, you'd like to inject it via annotations.
If the JNDI lookup is currently working for you without problems, and
If you're using Java EE 6+ (which I'm guessing you are), you can do the following:
#EJB(lookup = "jndi-lookup-string-here")
private RemoteInterface bean;
I am trying to make my first Java Enterprise Application and use UserTransactions.
Therefore I use JNDI Lookup with java:comp/UserTransaction to get my UserTransaction Object.
public void myMethod(MyEntity e) throws ApplicationException {
try {
this.ut = getUserTransaction();
this.ut.begin();
this.myStatefulBean.myBusinessMethod(e);
} catch ...
When I start my Transaction with .begin() and try to invoke any method in my stateful Bean (which works properly before starting a UserTransaction) I get an EJBTransactionRolledbackException which leads me to the following error:
java.lang.IllegalStateException: cannot add non-XA Resource to global JTS transaction
The Bean I am using is annotated with #DataSourceDefinition having className = "org.apache.derby.jdbc.ClientXADataSource" thus there is imo no non-XA Resource.
What am I doing wrong?
I am using openjpa 2.2.1, Java EE Version 6
Solved the problem by myself. I used in my DataSourceDefinition name = "java:global/jdbc/testDB" as name, but in my persistence.xml the DataSource name was defined as <jta-data-source>testDB</jta-data-source>
This seems to work in CMTs but not in a UserTransaction. Correcting the entry in persistence.xml to <jta-data-source>java:global/jdbc/testDB</jta-data-source> fixed the problem.