Jul 182007
 

Java Web application frameworks have been one of the important reasons for the success of enterprise Java. One wonders if Java EE would have been so successful without the Apache Struts framework. Although the underlying programming language is important, it’s often the frameworks that bring the language into the limelight. If you have been following the discussion forums, you will have noticed how that’s also the case with the Ruby language and the Ruby On Rails framework. Ruby has been around for more than a decade, yet only after the Ruby On Rails framework became a runaway hit did developers start noticing the Ruby language.

Scripting languages like Ruby, PHP, and Python have been growing in popularity over the past few years and, as a result, a need developed for a Java scripting alternative and a Rails-like framework for the Java world. Groovy is the scripting language and Grails is the framework.

In this article I will look at the Web development capabilities of Groovy and then move on to the Grails framework. I will develop a sample Grails Web application and look at the various features of the framework.

What is Groovy?

Groovy is a language that has a syntax that’s similar to, yet simpler than, Java. It’s often referred to as a scripting/agile/dynamic language, but I would prefer to stay away from these adjectives as I feel they only end up confusing things. If Java is a wise middle-aged man, Groovy is his teenage son. Groovy has many of the old man’s characteristics but is a lot wilder and a lot more fun. Both of them also work together
very well.

Groovy has a lot fewer rules than Java. For example, in Java to get the standard “Hello World” output, you need to write a class, a main method with proper arguments, and more. But in Groovy, if you
don’t wish to write all the boilerplate code, you can get rid of the class definition and the main method and just write the one line of code that actually prints “Hello World.”

So the contents of a file Hello.groovy that prints Hello World would be as follows:

println "Hello World"

The Java platform is concerned only with getting bytecodes to execute. As such, the platform does not force you to use the Java language. As long as you provide bytecodes, things will work. Groovy compiles to bytecodes, and it makes no difference to the Java platform if the bytecodes were generated from code written in Java or Groovy.

Here is an example of Groovy that shows Groovy’s built-in support for lists, maps, and range and also demonstrates the simplicity of Groovy and its capacity to leverage the power of Java:

// Print Date
def mydate = new java.util.Date()
println mydate

//Iterate through a map

def numbersMAP = ['1':'ONE', '2':'TWO']
for (entry in numbersMAP) {
    println "${entry.key} = ${entry.value}"
}

//Introducing the range
def range = 'a'..'d'

//Lists
def numberlist = [1, 2, 3, 4, 5, 6, 7, 8]
println numberlist;
println "Maximum value: ${numberlist.max()}"

Note that the above code directly uses java.util.Date and that the built-in support for collections cuts down on code required to work with lists, maps, and ranges. There are many other
interesting Groovy features like closures and simplified XML processing. You can find a detailed listing at groovy.codehaus.org.

Let’s now look at how you can use Groovy for Web development.

Web Development with Groovy

Most Java EE tutorials start with a basic servlet example. For Groovy Web development, you start with groovlets—the groovy parallel of servlets. If you get rid of the class and the doXX()
method declarations in a servlet, what you are left with would look a lot like a groovlet. An example is a groovlet file named Login.groovy that you will place in the top-level directory of your Web application:

def username= request.getParameter("username")
def password= request.getParameter("password")

if (username == "java" && password == "developer") {
  response.sendRedirect("home.jsp")
  session = request.getSession(true);
  session.setAttribute("name", username)
}
else {
  println """
  <h1>Login Invalid</h1>
  <p>Your IP has been logged > ${request.remoteHost}</p>
  """
  paramMap = request.getParameterMap()
  println "<p>You Submitted:</p>"
  for (entry in paramMap) {
  println "${entry.key} = ${entry.value}<br/>"
  }
}

You can just create a simple HTML form and send the action attribute of the form to action="Login.groovy". Next, you add these tags to your web.xml:

<servlet>
    <servlet-name>Groovy</servlet-name>
     <servlet-class>groovy.servlet.GroovyServlet</servlet-class>

</servlet>
<servlet-mapping>
      <servlet-name>Groovy</servlet-name>
     <url-pattern>*.groovy</url-pattern>
</servlet-mapping>

Now just add the required Groovy jar files to the WEB-INF/lib directory, and your Groovy Web application is ready to run on any Java EE application server.

You will have noticed the absence of semicolons in the code and also the usage of implicit variables like request and response. The other implicit variables are context, application,
session, out , sout, and html.

GSPs is the groovy parallel to JSPs. You do not use a println to generate HTML; you just embed your Groovy code within an HTML page. The example in this article will use GSPs while working with Grails.

Note that because everything comes down to bytecodes in the end, groovlets and GSPs can easily work with servlets and JSPs. So you do not have to pick either groovlets and GSP or servlets and JSPs.

Let’s now look at the promising Grails framework. If successful, Grails can significantly change the way you develop Java Web applications. Grails can do to Groovy what Ruby on Rails has done for Ruby.

Grails Features and Architecture

Grails attempts to use the “coding by convention” paradigm of Ruby On Rails to reduce the need for configuration files and other boilerplate code. With “coding by convention,” if you have a file whose name itself tells you what the file is doing, you do not need to restate the same thing in a configuration file. The framework will look at the filename and figure things out for itself. Using “coding by convention,” Grails will also auto generate a lot of things required in a Web application. Using Grails, you will have a working Web application ready in a short time and with minimal complexity. See below for an example.

Grails is based on open-source technologies like Spring, Hibernate, and SiteMesh. That’s a good thing if you are already good at these technologies but a not so good thing if you dislike these technologies for some reason or think that you have to not only learn Grails but also learn three other frameworks. Although these technologies help Grails perform better, learning four frameworks will seem like too-tough entry barrier to most. The Grails documentation currently highlights its integration with Spring, Hibernate, and other programs, however I think it needs to take the opposite approach and push Grails as a simple and fast Web application development framework. The developer need not worry or care about what happens underneath.

Fortunately, once you get going with Grails, you will see that Grails hides most of the underlying complexity of these frameworks. If you just forget that it’s Spring, Hibernate, and more working underneath, things will stay simple.

The three tiers of a Grails application are:

  • Web tier consisting of the views and controllers
  • Business logic tier consisting of domain classes and
    services
  • Persistence tier consisting of domain classes and data
    sources

Most frameworks have dozens of features of which very few get widely used. With Grails, the “coding by convention” paradigm and auto-generation of artifacts are these key features.

Other features of Grails are built-in support for Ajax, validations, unit testing, and functional testing. It uses the free and open-source Canoo WebTest project for functional testing of Web applications. Grails also provides integration with the Quartz Scheduler.

It’s time to install the Grails framework and write your first application.

Grails Installation

The installation procedure is quite simple. The Grails download page is here: http://grails.org/Download. You can download version 0.2.1 from http://dist.codehaus.org/grails/grails-bin-0.2.1.zip. Note that Grails source code and the documentation are available as separate downloads. After you download the zip file, just extract its contents to a directory, in my case C:\groovy\grails-0.2.1\.

Create a new environment variable named GRAILS_HOME and set its value to C:\groovy\grails-0.2.1\. Next add GRAILS_HOME\bin to the PATH environment variable. That’s it. You can check if the installation is okay by running the grails command on the command prompt. You should get usage information for the command.

Now that you have a working Grails installation, you’re ready to create a Grails Web application.

Developing a Grails Application: Application Structure

For years I have been planning to develop an application that will help me manage my clothes—an application that will tell me where my favorite t-shirt is placed, if it is washed, if it is
ironed, and so on. One day I intend to make millions selling this application, but for the time being I’ll use it for my Grails example.

The first step is creating a Grails project directory structure. For that I will create a new directory at C:\groovy\grailsapps and open a command prompt window at that level. Here, execute the
command grails create-app. You will be asked to enter an application name. Enter ClothesMgt. Grails will display all the directories and files it has created for you. Figure 1 shows the resulting directory structure.


alt=”Figure 1: Grails Project Directory Structure”>Figure 1: Grails project directory structure

The command will result in the creation of about 800 KB of files and directories. The idea here is that the framework is going with established Web application development conventions, so it creates
files and directories that would be useful in a majority of Web applications. Although some may not like this idea of being forced into a certain structure, this auto-generation based on conventions is where
the RAD features of Grails come from.

If you take a closer look at these directories, you will see that there are directories for things like controllers, views, tests, configuration files, and tag libraries. You will also find some basic
JavaScript and CSS files in place. So the basic structure of you app is now in place. You just fill in the blanks and the application will be ready.

Note that the commands that autogenerate directories and files are optional. You can do all the file and directory creation manually. If you are familiar with Apache Ant, you can even open up the file \src\grails\build.xml in the GRAILS_HOME directory and look at exactly what each Grails command is trying to achieve.

Database

For this example I will use a MySQL database named Clothes_Grails running on localhost. An HSQL database comes built-in with Grails and can be useful for testing simple applications
or just trying out Grails. If you use the HSQL DB, you will not have to execute the next few steps. I am using MySQL to demonstrate how easily you can use any database other than HSQL.

Download the MySQL driver from http://www.mysql.com/products/connector/j/ and place the mysql-connector-java-<version number>-stable-bin.jar file in the ClothesMgt\lib
directory. Next you need to edit the file ClothesMgt\grails-app\conf\ApplicationDataSource.groovy.

The contents of the file will now be similar to the following:

class ApplicationDataSource {
    boolean pooling = true
    String dbCreate = "create-drop"
    String url = "jdbc:mysql://localhost/Clothes_Grails"
    String driverClassName = "com.mysql.jdbc.Driver"
    String username = "grails"
    String password = "groovy"
}

Now let’s take a look at how you can make use of this database and object relational mapping.

Domain Classes

Grails’ Object Relational Mapping (GORM) capability uses Hibernate 3 internally, but you do not need to be aware of, or change, any Hibernate settings. Grails has something called “domain classes,”
whose objects are mapped to the database. You can link domain classes using relationships, and they also provide very powerful dynamic methods for CRUD (Create/Read/Update/Delete) operations.

For this example let’s create three domain classes named Shirt, Trouser, and Cabinet. To create a domain class, just run the command grails create-domain-class. Remember to run this command within your project directory and not in the directory above it. This is a common mistake that, although I have cautioned you, you will commit at least once.

The only input you must provide to the create-domain-class command is the class name. Run the command three times, giving Shirt, Trouser, and Cabinet as the names of the three domain classes. Grails
will now create the domain classes in the directory grails-app/domain/. These will have just two properties id and version. I will add properties to the classes to make them more representative
of a shirt, trouser, and a cabinet.

Listing 1: Cabinet.groovy

class Cabinet {
   Long id
   Long version
   String name
   String location
   def relatesToMany = [ shirts : Shirt, trousers : Trouser ]
   Set shirts = new HashSet()
   Set trousers = new HashSet()

   String toString() { "${this.class.name} :  $id" }

   boolean equals(other) {
       if(other?.is(this))return true
       if(!(other instanceof Cabinet)) return false
       if(!id || !other?.id || id!=other?.id) return false
       return true
   }

   int hashCode() {
       int hashCode = 0
       hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id &gt;&gt;&gt; 32)) )
   }
}

Listing 2: Trouser.groovy

class Trouser {
  Long id
  Long version
  String name
  String color
  Cabinet cabinet
  def belongsTo = Cabinet

  String toString() { "${this.class.name} :  $id" }

  boolean equals(other) {
     if(other?.is(this))return true
     if(!(other instanceof Trouser)) return false
     if(!id || !other?.id || id!=other?.id) return false
     return true
  }

  int hashCode() {
     int hashCode = 0
     hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id &gt;&gt;&gt; 32) ) )
  }
}

Listing 3: Shirt.groovy

class Shirt {
  Long id
  Long version
  String name
  String color
  Cabinet cabinet
  def belongsTo = Cabinet

  String toString() { "${this.class.name} :  $id" }

  boolean equals(other) {
      if(other?.is(this))return true
      if(!(other instanceof Shirt)) return false
      if(!id || !other?.id || id!=other?.id) return false
      return true
  }

  int hashCode() {
      int hashCode = 0
      hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id &gt;&gt;&gt; 32)))
  }
}

The only lines I have added are the ones where I declare the field names and color and then when I declare the relationship between Cabinet and Shirt and Trouser. Every Shirt and Trouser belongs to the Cabinet, and the Cabinet has a set of shirts and trousers. The belongsTo property is optional in this case, because in a one-many relationship, Grails always considers the one side as the owner. So you do not need to explicitly state so. Here I have done that just to make the relation obvious.

Next let’s look at the controller and view part of a Grails application.

Controllers and Views

Now that the domain classes are in place, let’s use the generate-all command to auto-generate the basic CRUD Web application. Run the grails generate-all command three times and when asked, provide a
domain class name. The generate-all command is supposed to generate the controller as well as the view for each domain class but due to bug-245 Grails 0.2.1 won’t generate the controller. You would have to generate the controller manually by using the command generate-controller for each domain class.

You should now see three controllers in the grails-app\controllers directory. These controllers are responsible for handling the requests in the Web application meant for a particular domain class. So ShirtController.groovy will handle the Shirt domain class-related CRUD requests in the Web application, and so on. The controller now has multiple closures, each
mapping to a URI. Closures is a nice feature of the Groovy language, however it does take some time to get used to it. Listing 4 shows an excerpt from Shirtcontroller.groovy.

Listing 4: ShirtController.groovy excerpt

class ShirtController {
    def index = { redirect(action:list,params:params) }
def list = { [ shirtList: Shirt.list( params ) ] } def show = { [ shirt : Shirt.get( params.id ) ] } def delete = { def shirt = Shirt.get( params.id ) if(shirt) { shirt.delete() flash.message = "Shirt ${params.id} deleted." redirect(action:list) } else { flash.message = "Shirt not found with id ${params.id}" redirect(action:list) } } // ... }

In this example, the list closure in the ShirtController will handle requests where the URI is /shirt/list, and so on. The controller is where you can work with things like requests, sessions, and servletContext that you would be used to working with in Java Web applications.

NOTE: Closures return a value either as an explicit return statement, or as the value of the last statement in the closure body. Do not get confused by the absence of return in the code generated by Grails.

Once the controller has finished processing a request, it must delegate to an appropriate view. For this, Grails uses a convention mechanism. So the list closure in ShirtController
will delegate to the view /grails-app/views/shirt/list.gsp or /grails-app/views/shirt/list.jsp. Although you are using Grails, all your views can be JSP files instead of GSP. I
have hardly written any code, yet I already have a Web application ready.

Let’s try deploying and running our application.

Deploying and Running Grails on a Java EE Server

Grails comes with a built-in Resin server, and you can run your application using the grails run-app command. The command will deploy your application to the Resin server and start the server. So you can now access the application at http://localhost:8080/ClothesMgt. However, you can just as easily deploy the application to any JavaEE server. I will try to deploy it on Tomcat. For this, all I need to do
is run the grails war command and copy the war file that gets generated to the webapps directory in Tomcat!

In this case the war file generated will have the name ClothesMgt.war. Once deployed on Tomcat, you should be able to access it at http://localhost:8080/ClothesMgt/ and get a screen as shown in Figure 2.


alt=”Figure 2: Grails Application”>
Figure 2: Grails application

With this application you get full CRUD functionality for the Shirt, Trouser, and Cabinet. You can display all data, add new shirts, and trousers to a cabinet, edit their values, and also delete the records—all without writing any business logic, view, or data access code. Within just a few minutes you have a proper Web application deployed on a JavaEE server. Cool, eh?!

Let’s go one step further and customize Grails.

Creating Custom Controllers

I will now add a new capability and pages to the Web application while reusing the domain classes already in place. While shirt/list and trouser/list display the list of shirts and trousers respectively, let’s now add a new display that will show a list of both shirts and trousers. To create a new display you need a new controller and view.

Auto-generating views and controllers using domain classes is easily done using the generate-controller and generate-views commands. However, in this case I want to create a controller that’s not directly associated with a domain class. So I will use the command grails create-controller. When prompted for a controller name, state Display. Grails will create a controller named DisplayController.groovy in the grails-app/controllers/ directory and a test suite in the grails-tests directory. Edit the controller as shown in Listing 5.

Listing 5: DisplayController.groovy

class DisplayController {

  def index = {redirect(action:list,params:params)}

  def list = {
        params['max'] = 10
        return [ shirtList: Shirt.list( params ),
                 trouserList: Trouser.list( params )]
  }
}

The index closure is redirecting requests to list. In the list closure I set the max param to 10 and then use the dynamic methods Shirt.list and Trouser.list. I then return a Groovy Map
that holds two lists, the shirt list and the trouser list.

As a Java developer, when you see Shirt.list(), you naturally expect a list method in the Shirt domain class. However, if you open Shirt.groovy, there’s no such method. This may not only be confusing but also be a dead end for a Java developer jumping into Grails without being aware of Groovy’s features. Dynamic methods are a special feature of Grails
and are built over a very special feature of the Groovy language—the Meta Object Protocol (MOP). It turns out that you can query the domain classes using dynamic methods. So, in the controllers, you will notice methods being called on the domain class, which don’t seem to exist in the domain class. You can read more on querying with dynamic methods here.

A reference to the dynamic methods available in Grails controllers and domain classes can be found here.

Now that the controller is capable of handling requests, getting the lists, and forwarding to the view, I need to create the corresponding view.

Create Custom View

When I created the controller, Grails also created a new display directory in the grails-app\views directory and added the following mapping in my web.xml file.

<servlet-mapping>
 <servlet-name>grails</servlet-name>
 <url-pattern>/display/*</url-pattern>
</servlet-mapping>

Grails currently has a generate-views command that is capable of generating a view based on a domain class, however there’s no create-view command that could auto-generate a view for you. See Figure 3 for an example.


alt=”Figure 3: A default view showing Trousers”>
Figure 3: A default view showing Trousers

As I wish to create a view independent of a domain class, let’s manually create the view file. Within the directory grails-app\views\display\, create a file named list.gsp, as shown in
Listing 6.

Listing 6: list.gsp

<html>
 <head>

  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <title>Display Shirt And Trouser List</title>
  <link rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}"></link>
 </head>
 <body>

   <div class="nav">
      <span class="menuButton"><a href="${createLinkTo(dir:'')}">Home</a></span>
  </div>
  <div class="body">
     <h1>Shirt List</h1>

      <table>
        <tr>
         <th>Id</th><th>Cabinet</th> <th>Color</th><th>Name</th>

        </tr>
        <g:each in="${shirtList}">
         <tr>
          <td>${it.id}</td> <td>${it.cabinet.name}</td>

          <td>${it.color}</td> <td>${it.name}</td>
         </tr>
        </g:each>
        </table>

        <h1>Trouser List</h1>
        <table>
         <tr>
           <th>Id</th> <th>Cabinet</th>

           <th>Color</th> <th>Name</th>
         </tr>
         <g:each in="${trouserList}">
           <tr>

             <td>${it.id}</td> <td>${it.cabinet.name}</td>
             <td>${it.color}</td> <td>${it.name}</td>

           </tr>
         </g:each>
        </table>
        </div>
    </body>
</html>

In similar fashion to what I did earlier, you can now either run the application using the run-app command, or create a war file and deploy it on Tomcat. You should see
the new view at http://localhost:8080/ClothesMgt/display/, as shown in Figure 4.


src=”http://www.indicthreads.com/images/stories/contentrelated/grails-fig4.gif”
alt=”Figure 4: Our newly created view listing shirts and trousers”>
Figure 4: The newly created view listing shirts and trousers

Let’s now have a quick look at Grails services.

Services

If you are wondering how you would separate your business logic and where you would put it, the answer lies in Grails Services. Services are named in the format SomeNameService.groovy
and placed in the directory /grails-app/services/. Services can make use of dependency injection features, and you can easily call these services from within controllers.

Let’s look at an example of how you can use a service. First, you will create your new service using the create-service command. Run the command and name the service Order. Grails will create
two files, grails-app/services/OrderService.groovy and grails-tests/OrderTests.groovy.

Now edit OrderService.groovy, as shown in Listing 7. The serviceMethod() is auto-generated while you have introduced a new orderGoods()
method.

Listing 7: OrderService.groovy

class OrderService {
  boolean transactional = true
  def serviceMethod() {
    // TODO
  }
  def orderGoods() {
    return "Order Placed - New shirts and trousers \
                              will be sent shortly."
  }
}

Now edit DisplayController, as shown in Listing 8. You introduce the reorder closure that uses the OrderService. Note that the service will be injected by Groovy.

Listing 8: DisplayController.groovy

class DisplayController {
  OrderService orderService    

  def index = {redirect(action:list,params:params)}

  def list = {
        params['max'] = 10
        return [ shirtList: Shirt.list( params )
            , trouserList: Trouser.list( params )]
  }    

  def reorder = {
         render(orderService.orderGoods())
  }

}

Now when you access the URL http://localhost:8080/ClothesMgt/display/reorder, the reorder closure will call the OrderService, and the response will be sent back to the browser. You can similarly
move all your business logic into services, and then use them quite easily using the injection capabilities of Grails.

Dynamic Methods and Properties

As noted earlier, the domain classes don’t have any methods like find(), findAll(), or save() that would fetch data from the database or update/delete existing data. In the controllers you have
not written methods like redirect() or render() either. But the domain classes and controllers serve their intended purpose and enable all required actions. The reason for this is the
presence of dynamic methods and properties in Grails. Dynamic methods are added to classes dynamically as if the functionality is compiled in the program.

These are the methods and properties that are available but you do not need to write. These dynamic methods cover most of the common scenarios that you would come cross in Web application development. For domain classes, there are dynamic methods like find(), findAll(), list(), executeQuery(), save(), and delete(). Controllers have dynamic properties like session, request, and response,
and dynamic methods like chain(), render(), and redirect(). To truly leverage the power of Grails, you need to be aware of the capabilities of all these dynamic methods and properties.

In Passing: Auto Reload and @Property

An important feature of Grails is its ability to auto-reload files as you make changes during development. So just edit and save a gsp file, and the new file will get auto-reloaded. Transactional services like the OrderService created here, however, don’t get reloaded. You will see the following message on the server console

Cannot reload class [class
OrderService] reloading of transactional service classes is not
currently possible. Set class to non-transactional first. “
.

The auto-reload capability of Grails should save you a lot of time that would otherwise be wasted on server restarts. I have come across some cases, like renaming a jsp file to gsp, where Grails was
unable to auto-reload. However, this capability of Grails can be expected to further improve in future versions.

Prior to the Groovy JSR 06 version, you had to use @Property to define any new property in Groovy. So you will see a number of old Groovy examples online that make use of @Property. Please note,
however, that @Property has been removed from Groovy JSR 06 and will also not be required in Grails 0.2 and later versions. Refer to the @Property proposal for more details.

Summary

In this article I introduced the basic features of the Grails framework and created an application using Grails. The best thing about Groovy and Grails is that everything runs on good old Java and Java EE—so you can develop applications quickly using the RAD features of Groovy and Grails, and then deploy applications on a reliable Java EE server. Considering the noise and hype around Ruby and Rails, there sure was a need for a Java alternative. Groovy and Grails look well-equipped to fill that space.

Download

Download code from this article:

References

Harshad Oak is the creator of the Java J2EE portal IndicThreads.com. He wrote Pro Jakarta Commons and Oracle JDeveloper 10g: Empowering J2EE Development as well as coauthored Java 2 Enterprise Edition 1.4 Bible. He is also the founder of Rightrix Solutions


Republished from dev2dev.

  • Lalit
    If you are beginning with GRAILS. You can check out this 
    http://lalitagarw.blogspot.com/2011/07/grails-sample-application-head-start.html
  • raymond
    Supreme !!!
  • http://www.amrsalah.com amr salah
    i can't thank you with the normal words for your efforts and your time i really liked it too much … thank you too much
    Great and awesome article
  • Helper
    try using java annotation @SuppressWarnings
  • Marno
    Hi,

    I am a Java dev and was merely looking for a overview of groovy and grails.

    You have out done yourself!

    Thanks for all your effort and for a great article! :)

  • Marno
    Hi,

    I am a Java dev and was merely looking for a overview of groovy and grails.

    You have out done yourself!

    Thanks for all your effort and for a great article! :)

  • Ghost_Trojan
    Great Article !!! Very useful for beginners
  • Ghost_Trojan
    Great Article !!! Very useful for beginners
  • Georges
    Hello,
    I’m already using grails to develop an interface, but my problem is that i already have tables created in Oracle with specific primary keys and i want to delete ID and VERSION from classes (i had modified all .groovy files and the views). When compiling i have a listing error (list.gsp).
    My problem is when connecting to my DB, i want to get all data without creating id and version in my db.
    Thank you in advance.
  • Georges
    Hello,
    I’m already using grails to develop an interface, but my problem is that i already have tables created in Oracle with specific primary keys and i want to delete ID and VERSION from classes (i had modified all .groovy files and the views). When compiling i have a listing error (list.gsp).
    My problem is when connecting to my DB, i want to get all data without creating id and version in my db.
    Thank you in advance.
  • Brahma
    Dear Shro Atulji Kahate, Have been struggling to get a good handle on these concepts for a long time, but could not find a good source. This article is perfect. Crisp and to the point. But very effective. Thank u.
  • Brahma
    Dear Shro Atulji Kahate, Have been struggling to get a good handle on these concepts for a long time, but could not find a good source. This article is perfect. Crisp and to the point. But very effective. Thank u.