using grails with legacy database - oracle

I faced with problem of using Grails with legacy Oracle database. I have legacy table TARGETTYPES with primary key text column TARGETTYPECODE:
CREATE TABLE "TMS"."TARGETTYPES"
( "TARGETTYPECODE" VARCHAR2(100) NOT NULL ENABLE,
"TARGETTYPEDESCR" VARCHAR2(255 CHAR),
"ACTIVE" CHAR(1) DEFAULT 'Y' NOT NULL ENABLE,
CONSTRAINT "TARGETTYPES_PK" PRIMARY KEY ("TARGETTYPECODE")
)
I created grails domain class:
package tmsconf
class Targettypes {
static transients = ['Targettypecode']
void setTargettypecode(String Targettypecode) {
id = Targettypecode
}
String getTargettypecode() {
return Targettypecode
}
String targettypedescr
String active
static mapping = {
table 'TARGETTYPES'
version false
columns {
id generator:'assigned', column:"TARGETTYPECODE", type:'text'
}
}
static constraints = {
id()
targettypecode(size: 1..100, blank: false)
targettypedescr(size: 0..255)
active(size: 1..1, blank: false)
id(nullable: true)
}
String toString() {
return "${targettypecode}"
}
}
Also I created controller class:
package tmsconf
class TargettypesController {
def scaffold = true
}
Application has started successfully.
When I click on link tmsconf.TargettypesController I have error in console:
Error 2012-10-10 10:55:37,243 [http-bio-8080-exec-9] ERROR util.JDBCExceptionReporter - ORA-00918: column ambiguously defined
| Error 2012-10-10 10:55:37,305 [http-bio-8080-exec-9] ERROR errors.GrailsExceptionResolver - SQLSyntaxErrorException occurred when processing request: [GET] /TMSConf/targettypes/list
ORA-00918: column ambiguously defined
. Stacktrace follows:
Message: ORA-00918: column ambiguously defined
Line | Method
->> 445 | processError in oracle.jdbc.driver.T4CTTIoer
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 396 | processError in ''
| 879 | processError . . . . in oracle.jdbc.driver.T4C8Oall
| 450 | receive in oracle.jdbc.driver.T4CTTIfun
| 192 | doRPC . . . . . . . in ''
| 531 | doOALL in oracle.jdbc.driver.T4C8Oall
| 207 | doOall8 . . . . . . in oracle.jdbc.driver.T4CPreparedStatement
| 884 | executeForDescribe in ''
| 1167 | executeMaybeDescribe in oracle.jdbc.driver.OracleStatement
| 1289 | doExecuteWithTimeout in ''
| 3584 | executeInternal . . in oracle.jdbc.driver.OraclePreparedStatement
| 3628 | executeQuery in ''
| 1493 | executeQuery . . . . in oracle.jdbc.driver.OraclePreparedStatementWrapper
| 96 | executeQuery in org.apache.commons.dbcp.DelegatingPreparedStatement
| 55 | <init> . . . . . . . in grails.orm.PagedResultList
| 15 | list in tmsconf.TargettypesController
| 186 | doFilter . . . . . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1110 | runWorker . . . . . in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . . in java.lang.Thread
Please help, where am I wrong

This should work:
package tmsconf
class Targettypes {
String targettypecode
String targettypedescr
String active
static mapping = {
version false
id generator: 'assigned', name: 'targettypecode'
}
static constraints = {
targettypecode(size: 1..100, blank: false)
targettypedescr(size: 0..255, nullable: true)
active(size: 1..1, blank: false)
}
String toString() {
targettypecode
}
}
You can now use the name property in the mapping block, so creating a transient get/set pair to wrap the id isn't needed.
I also removed the table name and column name settings since they're set to what would be used anyway, and removed type:'text' since Hibernate knows the type of the field, so it can use that for the type of the column.
Also, I added nullable: true for targettypedescr based on the SQL you showed.
In general when you're trying to map to legacy databases, use the http://grails.org/doc/latest/ref/Command%20Line/schema-export.html script to look at what Hibernate thinks the tables should look like. Tweak the constraints and mapping blocks until it's "close enough".

Related

Grails 2.4.5 Error net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException Invalid character ':' in value part of property

I get this error below when running a Grails 2.4.5 project (full stacktrace)
Error |
2021-11-28 01:27:44,302 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener - Error initializing the application: Error creating bean with name 'ehCacheManagementService': Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
Message: Error creating bean with name 'ehCacheManagementService': Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
Line | Method
->> 266 | run in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run in java.lang.Thread
Caused by CacheException: net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
->> 246 | init in net.sf.ehcache.management.ManagementService
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 266 | run in java.util.concurrent.FutureTask
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run . . . in java.lang.Thread
Caused by CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
->> 76 | createObjectName in net.sf.ehcache.management.Cache
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 64 | <init> in ''
| 107 | getCache in net.sf.ehcache.management.CacheManager
| 126 | getCaches in ''
| 237 | init . . in net.sf.ehcache.management.ManagementService
| 266 | run in java.util.concurrent.FutureTask
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run . . . in java.lang.Thread
Caused by MalformedObjectNameException: Invalid character ':' in value part of property
->> 618 | construct in javax.management.ObjectName
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1382 | <init> in ''
| 73 | createObjectName in net.sf.ehcache.management.Cache
| 64 | <init> in ''
| 107 | getCache in net.sf.ehcache.management.CacheManager
| 126 | getCaches in ''
| 237 | init . . in net.sf.ehcache.management.ManagementService
| 266 | run in java.util.concurrent.FutureTask
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run . . . in java.lang.Thread
Error |
2021-11-28 01:27:44,339 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener - Error initializing Grails: Error creating bean with name 'ehCacheManagementService': Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
Message: Error creating bean with name 'ehCacheManagementService': Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
Line | Method
->> 266 | run in java.util.concurrent.FutureTask
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run in java.lang.Thread
Caused by CacheException: net.sf.ehcache.CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
->> 246 | init in net.sf.ehcache.management.ManagementService
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 266 | run in java.util.concurrent.FutureTask
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run . . . in java.lang.Thread
Caused by CacheException: javax.management.MalformedObjectNameException: Invalid character ':' in value part of property
->> 76 | createObjectName in net.sf.ehcache.management.Cache
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 64 | <init> in ''
| 107 | getCache in net.sf.ehcache.management.CacheManager
| 126 | getCaches in ''
| 237 | init . . in net.sf.ehcache.management.ManagementService
| 266 | run in java.util.concurrent.FutureTask
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run . . . in java.lang.Thread
Caused by MalformedObjectNameException: Invalid character ':' in value part of property
->> 618 | construct in javax.management.ObjectName
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1382 | <init> in ''
| 73 | createObjectName in net.sf.ehcache.management.Cache
| 64 | <init> in ''
| 107 | getCache in net.sf.ehcache.management.CacheManager
| 126 | getCaches in ''
| 237 | init . . in net.sf.ehcache.management.ManagementService
| 266 | run in java.util.concurrent.FutureTask
| 1149 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 624 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 748 | run . . . in java.lang.Thread
Error |
2021-11-28 01:27:44,345 [localhost-startStop-1] ERROR core.StandardContext - Error listenerStart
Error |
2021-11-28 01:27:44,347 [localhost-startStop-1] ERROR core.StandardContext - Context [/soctrack-web] startup failed due to previous errors
|Server running. Browse to http://localhost:8080/soctrack-web
I am not sure what's causing the error, I get a successful "maven clean/package/install".
However, doing a "grails compile", I get a deprecated warning (as show below) from the cache-ehcache plugin, I am assuming that might be the reason why I am getting this error, but not sure how to solve it.
Note: C:\Users\kgeoffroy\Documents\dev\soc-track-upgrade\SOCScheduleServiceWEB\target\plugins\cache-ehcache-1.0.5\src\java\grails\plugin\cache\ehcache\G
railsEhCacheManagerFactoryBean.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
I will try to see if there are higher version of that plugin. So far I am constricted to a nexus mirror repository for the most part, so I haven't been able to find a higher version to test.
I have the sample dependencies inside my pom.xml
<dependency>
<groupId>org.grails.plugins</groupId>
<artifactId>cache-ehcache</artifactId>
<version>1.0.5</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.grails.plugins</groupId>
<artifactId>hibernate4</artifactId>
<version>4.3.8.1</version>
<scope>runtime</scope>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.grails.plugins</groupId>
<artifactId>tomcat</artifactId>
<version>7.0.55.2</version>
<scope>provided</scope>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.grails.plugins</groupId>
<artifactId>cache</artifactId>
<version>1.1.8</version>
<scope>compile</scope>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.grails.plugins</groupId>
<artifactId>cache-headers</artifactId>
<version>1.1.7</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.grails.plugins</groupId>
<artifactId>cached-resources</artifactId>
<version>1.1</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.1</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
According to an open issue https://github.com/grails-plugins/grails-cache-ehcache/issues/41, it might be a possible bug, but no solution or work around was provided.
I am doing an upgrade from Grails 2.2.0 to 2.4.5, I have updated the Datasource.groovy to point out to the right hibernate4 ehCache class:
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = true
// cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider' //Outdated class
// http://grails-plugins.github.io/grails-cache-ehcache/guide/usage.html
cache.region.factory_class = 'grails.plugin.cache.ehcache.hibernate.BeanEhcacheRegionFactory' // For Hibernate before 4.0
cache.region.factory_class = 'grails.plugin.cache.ehcache.hibernate.BeanEhcacheRegionFactory4' // For Hibernate before 4.0 and higher
}
config.groovy:
/*https://github.com/grails/grails-core/releases/tag/v2.4.5
* ehcache 2.9.0 is more strict about the configuration.
* ehcache is used in the spring-security-core plugin for caching users.
* There is a problem reported as GRAILS-12120.
* As a workaround to the "net.sf.ehcache.CacheException:
* Another unnamed CacheManager already exists in the same VM.
* " error you can add this config to Config.groovy:*/
beans {
cacheManager {
shared = true
}
}
I am trying to understand where that MalformedObjectNameException: Invalid character ':' in value part of property is coming from since the project didn't configure any ehcache, it just used some classes from the cache plugin. Here is a sample cache service implementation below:
GrailsEhCacheCache not recognized by IntelliJ GrailsCacheManager not recognized by IntelliJ
import grails.plugin.cache.GrailsCacheManager
import grails.plugin.cache.ehcache.GrailsEhcacheCache
import org.springframework.transaction.annotation.Transactional
class ChatCacheService
{
static transactional = false
static final String CHAT_CACHE_NAME = Chat.canonicalName
static final String CHAT_HASHES_CACHE_NAME = "${CHAT_CACHE_NAME}.Hashes"
GrailsCacheManager grailsCacheManager
ChatMessageCacheService chatMessageCacheService
FilterService filterService
GrailsEhcacheCache getChatCache()
{
grailsCacheManager.getCache(CHAT_CACHE_NAME) as GrailsEhcacheCache
}
GrailsEhcacheCache getChatHashesCache()
{
grailsCacheManager.getCache(CHAT_HASHES_CACHE_NAME) as GrailsEhcacheCache
}
void addNewChat(String chatChannelName, Chat chat)
{
chatMessageCacheService.createChatMessageCache(chatChannelName, chatCache)
chat.channelName = chatChannelName
refreshChat(chatCache, chat)
}
void refreshChat(Chat chat)
{
refreshChat(chatCache, chat)
}
void refreshChat(GrailsEhcacheCache chatCache, Chat chat)
{
chat.updateChatTimestamp()
chatCache.put(chat.channelName, chat)
// >>> Chat Cache Event listener will update hash, except during initialization
}
void refreshChatHash(Chat chat)
{
ChatHash chatHash = chat.generateHashCode(chatMessageCacheService.getCacheChatMessages(chat.channelName))
chatHashesCache.put(chat.channelName, chatHash)
}
Chat retrieveChat(String chatChannelName)
{
Chat chat = chatCache.get(chatChannelName)?.get() as Chat
chat
}
synchronized Chat retrieveNonPurgeableChat(String chatChannelName)
{
Chat chat = retrieveChat(chatChannelName)
if (!chat)
{
addNewChat(chatChannelName, new NonPurgeableChat())
chat = retrieveChat(chatChannelName)
}
chat
}
List<ChatChatMessage> getCacheChatMessages(String channelName)
{
chatMessageCacheService.getCacheChatMessages(channelName) //.sort { -it.id }
}
ChatChatMessage addNewChatMessageCache(String channelName, ChatMessage chatMessage)
{
Chat chat = retrieveChat(channelName)
chatMessageCacheService.addNewChatMessageCacheToTop(channelName, chatMessage)
refreshChat(chat) // refresh chat
}
void removeChat(String chatChannelName)
{
GrailsEhcacheCache chatCache = grailsCacheManager.getCache(CHAT_CACHE_NAME) as GrailsEhcacheCache
chatCache.evict(chatChannelName)
chatMessageCacheService.destroy(chatChannelName)
}
#Transactional(readOnly = true)
List<Chat> retrieveAllGeneralAndGroupChats()
{
List<Chat> generalAndGroupChats = []
List<ChatMessageType> generalAndGroupChatTypes = [
ChatMessageType.findByDescription(ChatType.GROUP.name()),
ChatMessageType.findByDescription(ChatType.GENERAL.name())
]
chatCache.allKeys.each { key ->
Chat chat = (Chat) chatCache.get(key).get()
if (generalAndGroupChatTypes.find { it?.description == chat?.chatTypeDescription })
{
generalAndGroupChats.add(chat)
}
}
generalAndGroupChats
}
void purgeOldMessagesFromChats()
{
chatCache.allKeys.findAll { String channelName -> !ChatService.isEventChat(channelName) }.each { String chatChannelName ->
Chat chat = (Chat) chatCache.get(chatChannelName).get()
if (!(chat instanceof NonPurgeableChat))
{
if (chatMessageCacheService.purgeOldMessages(chatChannelName) > 0)
{
refreshChat(chatCache, chat)
}
}
}
}
String getChatCacheHash(String channelName)
{
((ChatHash) chatHashesCache.get(channelName)?.get())?.hash
}
String synchronizeChat(UserProfile userProfile, String chatChannelName, String chatTimestamp, String selectedFilter)
{
String response = null
Chat chatToSynchronize = retrieveChat(chatChannelName)
if (chatToSynchronize && (chatTimestamp != getChatCacheHash(chatToSynchronize.channelName) || filterChanged(userProfile, selectedFilter)))
{
response = chatToJson(chatToSynchronize, filterService.getCurrentFilterForUsername(userProfile?.userId), selectedFilter, userProfile)
}
response
}
Boolean filterChanged(UserProfile userProfile, String selectedFilter) {
Boolean filterChanged = Boolean.FALSE
if (userProfile && userProfile?.groupChatFilterOption != selectedFilter
&& (userProfile?.groupChatFilterOption == SOCTrackConstants.DASHBOARD_FILTER || selectedFilter == SOCTrackConstants.DASHBOARD_FILTER)) {
filterChanged = Boolean.TRUE
}
filterChanged
}
String chatToJson(Chat chat, List<EventFilter> userFilters, String selectedFilter, UserProfile userProfile)
{
List<ChatChatMessage> chatChatMessages = chatMessageCacheService.getCacheChatMessages(chat.channelName)
// Apply dashboard filters
if (selectedFilter == SOCTrackConstants.DASHBOARD_FILTER) {
chatChatMessages = chatChatMessages.findAll{ChatChatMessage chatMessage ->
includeChatMessage(chatMessage, userFilters)
}
}
Map<String, Collection<String>> chatMessagesAndTimestamp = [:]
chatMessagesAndTimestamp['messages'] = chatChatMessages.collect { ChatChatMessage chatMessage ->
chatMessage.messageAsHtml = chatMessage.messageAsHtmlClone
if (! userProfile?.shouldHighlightGroupMessage(chatMessage.id, chatMessage.enteredDate, chatMessage.messageType) ||
chatMessage.enteredBy.equals(userProfile?.userId)) {
chatMessage.messageAsHtml = chatMessage.messageAsHtml.replaceAll("groupChatUnreadHighlight","")
}
if(chatMessage.lastResponseId > 0) {
if (!userProfile?.shouldHighlightGroupMessage(chatMessage.lastResponseId, chatMessage.lastResponseDate, chatMessage.messageType) ||
chatMessage.lastResponseBy.equals(userProfile?.userId)) {
chatMessage.messageAsHtml = chatMessage.messageAsHtml.replaceAll("groupChatResponseUnreadHighlight", "")
}
}
chatMessage.messageAsHtml
}.findAll { it }
chatMessagesAndTimestamp['chatTimestamp'] = getChatCacheHash(chat.channelName) // chat.chatTimestamp
JSON messagesAsJson = new JSON(chatMessagesAndTimestamp)
messagesAsJson.toString()
}
Boolean includeChatMessage (ChatChatMessage chatChatMessage, List<EventFilter> userFilters) {
boolean displayRow = true
if (userFilters) { //at least one filter to satisfy
boolean satisfiedAllAndFilters
boolean satisfiedAnOrFilter
List<EventFilter> andFilters = userFilters.findAll { eventFilter ->
eventFilter.filterOperationType == FilterOperationType.AND
}
List<EventFilter> orFilters = userFilters.findAll { eventFilter ->
eventFilter.filterOperationType == FilterOperationType.OR
}
if (andFilters) {
satisfiedAllAndFilters = andFilters.collect { andFilter ->
andFilter.displayChatBasedOnFilter(chatChatMessage)
}.every{ it } //all 'AND' filters must be satisfied
}
if (orFilters) {
satisfiedAnOrFilter = orFilters.collect { orFilter ->
orFilter.displayChatBasedOnFilter(chatChatMessage)
}.any{ it } //at least one 'OR' filter must be satisfied
}
displayRow = satisfiedAllAndFilters || satisfiedAnOrFilter
}
displayRow
}
}
UPDATE: Custom Utility method used to createEHcache
synchronized static Cache createEhcache(String name, CacheManager cacheManager, CacheConfiguration baseCacheConfiguration, CacheEventListener cacheEventListener = null)
{
Ehcache ehcache
PersistenceConfiguration persistenceConfiguration
if (cacheManager.cacheExists(name))
{
ehcache = cacheManager.getCache(name)
ehcache.cacheConfiguration.overflowToDisk = false //overflowToDisk deprecated
// ehcache.cacheConfiguration.persistence(persistenceConfiguration.strategy("LOCALTEMPSWAP"))
ehcache.cacheConfiguration.diskPersistent = false // diskPersistent deprecated
// ehcache.cacheConfiguration.persistence(persistenceConfiguration.strategy("NONE"))
ehcache.cacheConfiguration.timeToLiveSeconds = 0
ehcache.cacheConfiguration.timeToIdleSeconds = 0
logger.warn "Cache $name already exists, configuration has been reset."
}
else
{
baseCacheConfiguration.name = name
// ehcache = new Cache(baseCacheConfiguration, null, null); //Runtime error (Ambiguous method overloading)
// RegisteredEventListeners registeredEventListeners = new RegisteredEventListeners(null);
// BootstrapCacheLoader bootstrapCacheLoader = new RMIBootstrapCacheLoader()
ehcache = new Cache(baseCacheConfiguration, null as RegisteredEventListeners, null as BootstrapCacheLoader)
cacheManager.addCache(ehcache)
cacheManager.cacheManagerPeerProviders?.get('RMI')?.registerPeer("${getEhcachePeerBaseUrl()}/$baseCacheConfiguration.name")
if (cacheEventListener)
{
ehcache.getCacheEventNotificationService().registerListener(cacheEventListener)
}
}
ehcache
}
Putting that line of code inside the Config.groovy file solved the issue and removed the exception: grails.cache.ehcache.cacheManagerName = 'default_grails_cache'.
Solution comes from https://github.com/grails-plugins/grails-cache-ehcache/issues/41#issuecomment-985049476.

Grails 4 with spring-security-oauth2-provider:4.0.0-RC1

I created a Grails 4.0.2 application with this plugins:
compile 'org.grails.plugins:spring-security-core:4.0.0'
compile 'org.grails.plugins:spring-security-oauth2-provider:4.0.0-RC1'
I followed the documentation: https://bluesliverx.github.io/grails-spring-security-oauth2-provider/v3/manual/index.html
After I'm trying to use the authentication by:
curl -X POST \
-d "client_id=my-client" \
-d "grant_type=password" \
-d "username=my-user" \
-d "password=my-password" \
-d "scope=read" http://localhost:8080/oauth/token
But I receive this error:
URI
/oauth/token
Class
java.lang.IllegalArgumentException
Message
There is no PasswordEncoder mapped for the id "null"
Trace
Line | Method
->> 244 | matches in org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 198 | matches in org.springframework.security.crypto.password.DelegatingPasswordEncoder
| 90 | additionalAuthenticationChecks in org.springframework.security.authentication.dao.DaoAuthenticationProvider
| 166 | authenticate in org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
| 175 | authenticate . . . . . . . . . in org.springframework.security.authentication.ProviderManager
| 123 | attemptAuthentication in org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter
| 212 | doFilter . . . . . . . . . . . in org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
| 334 | doFilter in org.springframework.security.web.FilterChainProxy$VirtualFilterChain
| 105 | doFilter . . . . . . . . . . . in org.springframework.security.web.context.SecurityContextPersistenceFilter
| 334 | doFilter in org.springframework.security.web.FilterChainProxy$VirtualFilterChain
| 58 | doFilter . . . . . . . . . . . in grails.plugin.springsecurity.web.SecurityRequestHolderFilter
| 334 | doFilter in org.springframework.security.web.FilterChainProxy$VirtualFilterChain
| 215 | doFilterInternal . . . . . . . in org.springframework.security.web.FilterChainProxy
| 178 | doFilter in ''
| 193 | internalDoFilter .
I find this solution:
https://mkyong.com/spring-boot/spring-security-there-is-no-passwordencoder-mapped-for-the-id-null/
but I don't know how apply the solution on the grails project.
Anyone could help me?
Thank you,
Cristian
I too ran into this issue but I believe I found the answer.
Add this to the Client class that the oauth plugin init script generates:
static mapping = {
autowire true
}
Or add this to the runtime.groovy to enable service injection to all domain classes by default
grails-app/conf/runtime.groovy
grails.gorm.default.mapping = {
autowire true
}
As for the reason this is happneing. The Client Domain class tries to call this code before being inserted:
protected void encodeClientSecret() {
clientSecret = clientSecret ?: NO_CLIENT_SECRET
clientSecret = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(clientSecret) : clientSecret
}
But it fails to encode the password correctly since the spring security service is null.
The Grails documentation mentions that starting with Grails 3.3.0, services are not longer injected by default in Domain classes and need that mapping to be injected.
I temporary solved my question by setting in the resources.groovy
beans = {
userSecPasswordEncoderListener(UserSecPasswordEncoderListener)
passwordEncoder(NoOpPasswordEncoder) {
}

Grails custom validation message, error

I was trying to add a custom message to my validator like this:
static constraints = {
joining validator: { val, obj ->
if(val?.after(obj.birthday)) return 'joining.error'
}
}
Of course I adjusted the messages.properties file. I'm getting the following exception:
2015-04-30 16:52:27,253 [localhost-startStop-1] ERROR context.GrailsContextLoaderListener - Error initializing the application: No signature of method: usermanagement.UserRole.exists() is applicable for argument types: (null, java.lang.Long) values: [null, 1]
Possible solutions: exists(long, long), exists(java.io.Serializable), list(), first(), wait(), last()
Message: No signature of method: usermanagement.UserRole.exists() is applicable for argument types: (null, java.lang.Long) values: [null, 1]
Possible solutions: exists(long, long), exists(java.io.Serializable), list(), first(), wait(), last()
Line | Method
->> 92 | methodMissing in org.grails.datastore.gorm.GormStaticApi
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 86 | doCall in usermanagement.UserRole$__clinit__closure9$_closure14$_closure15
| 85 | doCall . . . . . . . . . . . . . in usermanagement.UserRole$__clinit__closure9$_closure14
| 44 | create in usermanagement.UserRole
| 19 | doCall . . . . . . . . . . . . . in BootStrap$_closure1
| 327 | evaluateEnvironmentSpecificBlock in grails.util.Environment
| 320 | executeForEnvironment . . . . . in ''
| 296 | executeForCurrentEnvironment in ''
| 266 | run . . . . . . . . . . . . . . in java.util.concurrent.FutureTask
| 1142 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 617 | run . . . . . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run in java.lang.Thread
I dont really understand why there is a connection to usermanagement.UserRole.exists()?
EDIT: UserRole is generated by the SpringSecurity core Plugin
EDIT: Bootstrap.groovy:
import java.text.SimpleDateFormat
import usermanagement.*
class BootStrap {
def init = { servletContext ->
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
def birthday_sdf = new SimpleDateFormat("dd-M-yyyy hh:mm:ss")
def birthday_str = "31-08-1982 10:20:56"
def testUser = new User(username: 'me', password: 'password',
firstName: 'Adam', lastName: 'Administrator',
role: adminRole, email: 'test#gmail.com',
birthday: birthday_sdf.parse(birthday_str), joining: new Date())
testUser.save(flush: true)
UserRole.create testUser, adminRole, true
}
}
I just saw that the statement in the validator is wrong:
if(val?.after(obj.birthday)) return 'joining.error'
should be
if(!(val?.after(obj.birthday))) return 'joining.error'
Because of that the joining I set in the Bootstrap.groovy was not valid which should be the root of the problem.

How can I retrieve the Geolocation from an IP address in Grails?

I want to retrieve the geolocation from an IP-address in a Grails app.
I tried hostip and geoip both raise exceptions and did not work for me. Is there any other way to get the geolocation?
When I use geoip I have:
config.groovy:
geoip.data.resource= "/WEB-INF/GeoLiteCity.dat"
geoip.data.cache="GEOIP_STANDARD"
In my controller:
GeoIpService geoIpService
index() {
def location = geoIpService.getLocation("85.176.52.75")
render location.countryName + " " + location.city
}
The exception is:
| Error 2013-07-26 14:04:22,236 [http-bio-8090-exec-1] ERROR
errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [GET] /test/home/index
Stacktrace follows:
Message: null
Line | Method
->> 199 | <init> in java.util.StringTokenizer
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 221 | <init> in ''
| 624 | getLocationwithdnsservice in com.maxmind.geoip.LookupService
| 593 | getLocation in ''
| 42 | getLocation . . . . . . . in org.grails.geoip.service.GeoIpService
| 12 | index in test.HomeController
| 195 | doFilter . . . . . . . . in
grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1145 | runWorker . . . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . . . . . in java.lang.Thread
After downloading your sample grails app from github, and after debugging it for a while, I found out what the problem is. Well, there are 2 problems really:
Your configuration for the geoip plugin is incorrect
The documentation for the geoip plugin makes it look like the configuration you have is correct, when it is not.
If you take a look at the documentation for the plugin: http://grails.org/plugin/geoip you will see that it talks about the configuration for the geoip.data.cache as follows:
geoip.data.cache - There are 4 possible values for this:
0 - GEOIP_STANDARD
1 - GEOIP_MEMORY_CACHE
2 - GEOIP_CHECK_CACHE
4 - GEOIP_INDEX_CACHE
So what it is actually looking for is the integer values, not the strings beside them. For example, 0 is used for GEOIP_STANDARD, so you configure it with:
geoip.data.cache=0
When I changed the configuration of your sample app to the above, I no longer get the exceptions.

Why Grails is using H2 instead of Oracle?

I have spent a lot of time to resolve this problem. I'm begginer in GRAILS and GROOVY.
I have legacy oracle database schema named "tms_dev". This schema has some tables (for example checktypes table). Also I have domain class Checktype and ChecktypesController class - controller generated by GRAILS.
This class has list method:
def list(Integer max) {
params.max = Math.min(max ?: 10, 100)
[checktypesInstanceList: Checktypes.list(params), checktypesInstanceTotal: Checktypes.count()]
}
Also I configured Datasource.groovy file to work with oracle with such contents
dataSource {
pooled = true
driverClassName = "oracle.jdbc.OracleDriver"
dialect = "org.hibernate.dialect.Oracle10gDialect"
username = "TMS_DEV"
password = "password"
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}
development {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop','update'
url = "jdbc:oracle:thin:#server_name:1522:sid_name"
}
}
production {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop','update'
url = "jdbc:oracle:thin:#server_name:1522:sid_name"
}
}
I run my application. And click "tst7.ChecktypesController" refence on the main page.
As a result I have exception:
| Error 2012-08-27 14:41:03,469 [http-bio-8080-exec-9] ERROR util.JDBCExceptionReporter - Table "CHECKTYPES" not found; SQL statement:
select * from ( select this_.CHECKTYPECODE as CHECKTYP1_21_0_, this_.active as active21_0_, this_.availabilitychecktype as availabi3_21_0_, this_.checktypecode as checktyp1_21_0_, this_.checktypedescr as checktyp4_21_0_, this_.TARGETTYPECODE as TARGETTY5_21_0_ from CHECKTYPES this_ ) where rownum <= ? [42102-164]
| Error 2012-08-27 14:41:03,547 [http-bio-8080-exec-9] ERROR errors.GrailsExceptionResolver - JdbcSQLException occurred when processing request: [GET] /Tst7/checktypes/list
Table "CHECKTYPES" not found; SQL statement:
select * from ( select this_.CHECKTYPECODE as CHECKTYP1_21_0_, this_.active as active21_0_, this_.availabilitychecktype as availabi3_21_0_, this_.checktypecode as checktyp1_21_0_, this_.checktypedescr as checktyp4_21_0_, this_.TARGETTYPECODE as TARGETTY5_21_0_ from CHECKTYPES this_ ) where rownum <= ? [42102-164]. Stacktrace follows:
Message: Table "CHECKTYPES" not found; SQL statement:
select * from ( select this_.CHECKTYPECODE as CHECKTYP1_21_0_, this_.active as active21_0_, this_.availabilitychecktype as availabi3_21_0_, this_.checktypecode as checktyp1_21_0_, this_.checktypedescr as checktyp4_21_0_, this_.TARGETTYPECODE as TARGETTY5_21_0_ from CHECKTYPES this_ ) where rownum <= ? [42102-164]
Line | Method
->> 329 | getJdbcSQLException in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 169 | get in ''
| 146 | get . . . . . . . . . . . in ''
| 4753 | readTableOrView in org.h2.command.Parser
| 1080 | readTableFilter . . . . . in ''
| 1686 | parseSelectSimpleFromPart in ''
| 1793 | parseSelectSimple . . . . in ''
| 1680 | parseSelectSub in ''
| 1523 | parseSelectUnion . . . . in ''
| 1022 | readTableFilter in ''
| 1686 | parseSelectSimpleFromPart in ''
| 1793 | parseSelectSimple in ''
| 1680 | parseSelectSub . . . . . in ''
| 1523 | parseSelectUnion in ''
| 1511 | parseSelect . . . . . . . in ''
| 405 | parsePrepared in ''
| 279 | parse . . . . . . . . . . in ''
| 251 | parse in ''
| 217 | prepareCommand . . . . . in ''
| 415 | prepareLocal in org.h2.engine.Session
| 364 | prepareCommand . . . . . in ''
| 1121 | prepareCommand in org.h2.jdbc.JdbcConnection
| 71 | <init> . . . . . . . . . in org.h2.jdbc.JdbcPreparedStatement
| 267 | prepareStatement in org.h2.jdbc.JdbcConnection
| 281 | prepareStatement . . . . in org.apache.commons.dbcp.DelegatingConnection
| 313 | prepareStatement in org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
| 55 | <init> . . . . . . . . . in grails.orm.PagedResultList
| 45 | list in tst7.ChecktypesController
| 195 | doFilter . . . . . . . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1110 | runWorker . . . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . . . . . in java.lang.Thread
Then I tried to create direct Oracle connection in list method
def list(Integer max) {
def sql = Sql.newInstance("jdbc:oracle:thin:#server_name:1522:instance_name", "TMS_DEV",
"password", "oracle.jdbc.driver.OracleDriver")
sql.eachRow("select * from Dbdrivers"){
println it.dbdrivercode
}
}
Than I run application. As result println it.dbdrivercode - works fine (CONNECTION WORKS!!!).
Most strange in this problem is that exception is generated by h2 (H2 in memory database) class (org.h2.jdbc.JdbcConnection
,org.h2.jdbc.JdbcConnection
and so on).
You are defaulting to the H2 driver because your production and development blocks are being ignored when outside an environments block.
sounds like application cache issue. try running grails clean before running the app.

Resources