am facing NonSqlTransientException Null userid not supported while starting the liberty server where my server.xml contain authdata
The authData configuration in Liberty is only for container managed authentication. If you are using application authentication (as is the case for JNDI lookup without resource reference, or if using a resource reference that is set to authentication type of Application), then authData does not apply. If you are using a resource reference with Container authentication, then you can use the authData, but there is an additional configuration step to associate the authData with the dataSource. This can be done in either of the following ways, documented in this knowledge center article.
One option is to configure the containerAuthDataRef of the dataSource to point at the id of the authData element (you'll need to add an id for it if it doesn't have one). Here is an example,
<authData id="myAuth" user="user1" password="pwd1"/>
<dataSource jndiName="jdbc/myDataSource" containerAuthDataRef="myAuth">
<jdbcDriver libraryRef=...
<properties...
</dataSource>
The other option is to specify the authData's id under the authentication-alias in the application's bindings (such as ibm-web-bnd.xml or ibm-ejb-jar-bnd.xml) for the data source. For example, the following bindings are based on the server config from the previous example,
<resource-ref name="java:app/env/jdbc/myDataSourceRef" binding-name="jdbc/myDataSource">
<authentication-alias name="myAuth"/>
</resource-ref>
It should be noted that the former is a default for container authentication that is used in the absence of the latter. So if you specify both ways, then the latter takes precedence and will be used instead.
Related
When deploying "regular" web apps to Liberty, I was used to binding the global datasource configured in Liberty's server.xml to the individual application by using a child element within the element, like this:
<application context-root="helloApp" location="..." name="helloApp" type="war">
<application-bnd>
<data-source id="db2appDs" name="jdbc/datasource" binding-name="jdbc/theDB"/>
</application-bnd>
...
</application>
<dataSource id="db2ds" jndiName="jdbc/theDB" type="javax.sql.DataSource">
...
</dataSource>
When configuring my first Spring Boot application to deploy to Liberty, I am trying to use the new <springBootApplication> element for it - but I don't seem to be able to add a binding for the datasource I want to use the same way, as this element doesn't seem to support such a child. (It seems to want only <classloader> as a child).
I've seen people suggest I use an #Resource annotation that includes both application-local JDNI name and global JNDI name for the datasorce - but that defeats the purpose, since I don't want to know what the global name is until deploy time.
Is there another way to do this, like we used to before? Or are applications deployed through <springBootApplication> expected to know the global JNDI name of the datasource(s) they want?
Application-defined datasources are not supported for <springBootApplication/>’s. While your application may certainly access a Liberty datasource using its global JNDI name, you should configure the spring.datasource.jndi-name property within your Spring Boot application as described in section 29.1.3 of the Spring Boot features reference. For your example try spring.datasource.jndi-name=jdbc/theDB.
I am using WebSphere 8.5.5.18.
As of now I'm using Component-Managed Authentication Alias for my DataSource. But I want to use Container-Managed instead. When I just change the Security settings in Data Sources → Security settings I am getting error in logs. It is unable to fetch records.
Exception Stacktrace:
Check the SQL Statement (preparation failed).
--- Cause: java.sql.SQLException: [jcc][t4][10205][11234][3.72.54] Null userid is not supported. ERRORCODE=-4461, SQLSTATE=42815 DSRA0010E: SQL State = 42815, Error Code = -4,461
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:97)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:212)
at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForObject(SqlMapClientTemplate.java:271)
Basically the database is not being accessed properly when settings are changed from Component-Managed Authentication to Container-Managed Authentication alias.
When I run with Component-Managed Authentication, its working fine.
Does changing security setting to Container Managed Authentication alias, require some other/additional setting/changes? Or do I need to change my underlying Spring ibatis code to make it work?
Any help on configuring/implementing Container-Managed Authentication Alias in websphere would be appreciated.
Container-managed authentication applies when your code (or any third party code that executes upon its behalf) looks up the data source with a resource reference that specifies the resource authentication as container or leaves resource authentication unspecified, in which case it defaults to container.
Component-managed authentication applies when your code (or any third party code that executes upon its behalf) looks up the data source without a resource reference, or uses a resource reference that specifies the resource authentication as application.
Here are some examples of resource references that use container authentication:
// resource injection can be used on a web component (servlet) or ejb component
#Resource(name = "java:comp/env/jdbc/ds1ref", lookup = "jdbc/ds1", authenticationType = Resource.AuthenticationType.CONTAINER)
DataSource ds1;
#Resource(name = "java:comp/env/jdbc/ds2ref", lookup = "jdbc/ds2")
DataSource ds2;
...
// code that looks up one of the above resource references
DataSource ds = InitialContext.doLookup("java:comp/env/jdbc/ds1ref");
Here is an example of a resource reference defined within a web.xml deployment descriptor:
<resource-ref>
<res-ref-name>java:comp/env/jdbc/ds3ref</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<lookup-name>jdbc/ds3</lookup-name>
</resource-ref>
If third party code, such as Spring, is looking up a data source on your behalf and you would like it to use container authentication, you will need to define a resource reference with container managed authentication, such as shown above in the examples, and supply its resource reference name to the third party software in place of however you are doing so currently. If you are unsure where this is done, it might help to search for occurrences of the configured JNDI name of the WebSphere data source within the application.
I'm new to JPA and Liberty. Could anyone please explain how to relate/link the server.xml, web.xml and persistence.xml configuration to set up the database connection?
your help on this is much appreciated.
In Liberty, you define the location of the JDBC driver jar files and configure a dataSource element with a JNDI name. This knowledge center page contains an example for MySQL,
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_dep_configuring_ds.html
Directly quoting from the above page,
<dataSource id="DefaultDataSource" jndiName="jdbc/mySQL">
<jdbcDriver libraryRef="MySQLLib"/>
<properties databaseName="SAMPLEDB" serverName="localhost" portNumber="3306"/>
</dataSource>
<library id="MySQLLib">
<file name="C:/mysql-connector-java-x.x.xx/mysql-connector-java-x.x.xx.jar"/>
</library>
After this, you can configure the jta-data-source element in your persistence.xml pointing at the JNDI name that you chose. For example,
...
<persistence-unit name="ExamplePersistenceUnit">
<jta-data-source>jdbc/mySQL</jta-data-source>
</persistence-unit>
The above is sufficient to get it working, without involving web.xml.
The deployment descriptor (web.xml) gives you the option of adding a level of indirection/mapping and the ability to configure some additional settings such as shareability and container vs application authentication. You can do this by defining a resource reference in web.xml pointing to the data source. Resource references have names in java:comp/env, java:module/env, java:app/env or java:global/env that reflect their visibility. I'll use java:module in the following example, meaning that the reference we are defining is only visibility within the same module (the web module that provides the web.xml),
<resource-ref>
<res-ref-name>java:module/env/jdbc/mySQLRef</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
<lookup-name>jdbc/mySQL</lookup-name>
</resource-ref>
After defining the resource reference above, the data source continues to be available at the JNDI name specified in server.xml, but also becomes available via the JNDI name of the resource reference, meaning you could alternately specify,
<jta-data-source>java:module/env/jdbc/mySQLRef</jta-data-source>
Deployment descriptors can also do some more advanced things like defining a data source in place of the server config. However, to keep this answer simple, I've skipped over that possibility.
This IBM KnowledgeCenter topic is a good place to start
I have a server.xml with jndi configuration that works and can connect to database (validated with small program using #Resource), but when I try to use an application that is spring based, I can never login to the database. I am successfully getting the jndi reference, but it just never logs in and gives me invalid username/password.
I have searched this to death on google, and haven't found anything that can point in the right direction.
You should post the specific details about your configuration and resource references. One way to cause the error you are seeing would be to configure a dataSource with the user/password specified only within the default container authdata (dataSource with nested containerAuthData element, or with a containerAuthDataRef specified). When you use #Resource, you are getting container authentication by default, and the user/password would be used. However, if Spring is directly looking up the data source (no resource reference) or specifies a resource reference with application authentication, then the user/password of the default container authdata would not apply. However, if instead you configure user/password on the vendor properties element that is nested under dataSource, then it will reply regardless of the authentication type.
Example of data source configuration where user/password will only be used for container authentication:
<dataSource id="DefaultDataSource" jndiName="jdbc/oracle">
<containerAuthData user="user1" password="pwd1"/>
<jdbcDriver libraryRef="OracleLib"/>
<properties.oracle URL="jdbc:oracle:thin:#//localhost:1521/SAMPLEDB"/>
</dataSource>
Example of data source configuration where user/password apply regardless of whether container or application authentication are used,
<dataSource id="DefaultDataSource" jndiName="jdbc/oracle">
<jdbcDriver libraryRef="OracleLib"/>
<properties.oracle URL="jdbc:oracle:thin:#//localhost:1521/SAMPLEDB" user="user1" password="pwd1"/>
</dataSource>
invalid username/password is an oracle error message, so you may be:
pointing to the wrong DB (where user does not live)
using the wrong user
using the wrong password
Try the connection in SQL Plus, if it works there, then problem in the code/configuration.
I have some Java code running on Liberty Profile which authenticates with MS Active Directory and makes LDAP searches. The code use JNDI and does what it is intended to do. The problem is that the LDAP parameters are hard coded in Java. Works, but could be improved:
ldap.put(Context.PROVIDER_URL, "ldap://ad.foo.bar:389");
ldap.put(Context.SECURITY_PRINCIPAL, "CN=account,OU=A,DC=ad,DC=foo,DC=bar");
ldap.put(Context.SECURITY_CREDENTIALS, "apoorlykeptsecret");
...
ldapCtxt = new InitialDirContext(ldap);
Is it possible to pick the LDAP properties up from an ldapRegistry element in the server.xml file instead? Or am I on the wrong track? Is there a better way to approach this?
Yes, you should be able to configure that using the <ldapRegistry> element in server.xml.
For example:
<ldapRegistry id="ldap" realm="SampleLdapADRealm"
host="ldapserver.mycity.mycompany.com" port="389"
baseDN="cn=users,dc=adtest,dc=mycity,dc=mycompany,dc=com"
bindDN="cn=testuser,cn=users,dc=adtest,dc=mycity,dc=mycompany,dc=com"
bindPassword="testuserpwd"
ldapType="Microsoft Active Directory">
<activedFilters
userFilter="(&(sAMAccountName=%v)(objectcategory=user))"
groupFilter="(&(cn=%v)(objectcategory=group))"
userIdMap="user:sAMAccountName"
groupIdMap="*:cn"
groupMemberIdMap="memberOf:member" >
</activedFilters>
</ldapRegistry>
For full doc see: Configuring LDAP user registries in Liberty
As an alternative quick approach, you could put those values in your server.xml configuration as JNDI entries and obtain the values in your application by JNDI lookup. For example:
<jndiEntry jndiName="ldap/provider_url" value="ldap://ad.foo.bar:389"/>
<jndiEntry jndiName="ldap/secuirty_principal" value="CN=account,OU=A,DC=ad,DC=foo,DC=bar"/>
<!-- WARNING: Storing passwords is JNDI is not secure -->
<jndiEntry jndiName="ldap/security_credentials" value="apoorlykeptsecret"/>
String providerUrl = InitialContext.doLookup("ldap/provider_url");
// etc...