воскресенье, 28 сентября 2008 г.

Connect to mysql 5 with Tomcat 6

When I try to solve this problem I read two docs: help in Netbeans 6(http://www.netbeans.org/kb/60/web/mysql-webapp.html#settingUpConnPool) and jndi help from tomcat.apache.org(http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html). But when I lookup InitialContext, application throws NamingException. I spent over four hours to solve this problem. As I've understood, when I create resource in context.xml which placed in web application, Tomcat dont put it in global resources and when I connect to this resource, I should write prefix java:comp/env/ before actual resource name. I replace this line:

Datasource ds = (Datasource)ic.lookup("jdbs/sambledb");

with this:

Datasource ds = (Datasource)ic.lookup("java:comp/env/jdbs/sambledb");

YES! Lookup result was successfull.

I use oficial recommended jconnector version 5.1 from mysql.com. I copy jar with connector in TOMCAT_HOME/lib/, but I get ClassNotFoundException.... after long four or five hours I hate Window Vista, Tomcat, Netbeans, Java, Computers and...my life :) . I cannt direct solve this problem. I have no ideas how services in Windows works, but when I uninstall Tomcat which I downloaded from link with name Windows Service Installer(http://www.sai.msu.su/apache/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.exe) and install simple zip version (http://www.sai.msu.su/apache/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.zip) all works ok(YEAH!) :)

Some tips:

-Don't use empty password in mysql to connect.

-In different cases Tomcat throws exception sounds like this - driver "com.mysql.jdbc.Driver" not found. You can reduce number of meanings if insert in your code this line - Class.forName("com.mysql.jdbc.Driver").

-DONT USE SERVICE INSTALLER VERSION OF TOMCAT!!!(I like init.d:))

Finally I have something like this:

web.xml:

<resource-ref>
<description>jdbc:mysql://localhost:3306/mynewdatabase</description>
  <res-ref-name>jdbc/mynewdatabase/<res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

context.xml:

<Resource name="jdbc/mynewdatabase" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="javauser" password="qwerty" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/mynewdatabase"/></resource>

sample method to test connection:
...
public String getEmployers() {
  try {
    InitialContext ic = new InitialContext();
    DataSource ds = (DataSource)   ic.lookup("java:comp/env/jdbc/mynewdatabase");
    Connection con = ds.getConnection(); //NO User and Password, we set it in Resource
    Statement st = con.createStatement();

    ResultSet rs = st.executeQuery("SELECT * FROM employers");

    String ret = "Employers ";
    while (rs.next()) {
      ret += rs.getString("name") + ",";
    }
    return ret;
  } catch (SQLException ex) {
    return ex.getMessage();
  } catch (NamingException ex) {
    return ex.getMessage();
  }
}
...

If you have troubles, write its in comments and I try to help you.

понедельник, 15 сентября 2008 г.

Wrapper for JComponent

Trouble: we have some JComponent. We need paint this component and remove all logic from it.

At the begining, I think that solution is very simple: override paint() method, and draw inner component in wrpapper's Graphics.

public class ComponentWrapper extends JComponent {
  private JComponent innerComponent;

  public ComponentWrapper(JComponent innerComponent) {
      this.innerComponent = innerComponent;
  }

  @Override
  public void paint(Graphics g)
  {
      if (innerComponent != null) {
          innerComponent.paint(g);
      }
  }

}

But I don't see innerComponent, because it hasn't bound. We should delegate methods that set sizes and bound on innerComponent. Now our wrapper looks like this:

public class ComponentWrapper extends JComponent {
  private JComponent innerComponent;

  public ComponentWrapper(JComponent innerComponent) {
      this.innerComponent = innerComponent;
  }

  @Override
  public void paint(Graphics g) {
      innerComponent.paint(g);
  }
   
  @Override
  public void setMaximumSize(Dimension maximumSize) {
      super.setMaximumSize(maximumSize);
      innerComponent.setMaximumSize(maximumSize);
  }

  @Override
  public void setMinimumSize(Dimension minimumSize) {
      super.setMinimumSize(minimumSize);
      innerComponent.setMinimumSize(minimumSize);
  }

  @Override
  public void setPreferredSize(Dimension preferredSize) {
      super.setPreferredSize(preferredSize);
      innerComponent.setPreferredSize(preferredSize);
  }

  @Override
  public void setBounds(Rectangle r) {
      super.setBounds(r);
      innerComponent.setBounds(r);
  }

  @Override
  public void setBounds(int x, int y, int width, int height) {
      super.setBounds(x, y, width, height);
      innerComponent.setBounds(x, y, width, height);
  }

  @Override
  public void setSize(int width, int height) {
      super.setSize(width, height);
      innerComponent.setSize(width, height);
  }
}


At first blush all is ok. But if we wrap JPanel with some layout, we dont see anything. This occurs because components in panel haven't sizes. We should apply layout on panel. JComponent have a wonderful method - doLayout(). Now, when our wrapper change size, we need call innerComponent.doLayout() and after this components in panel will have actual sizes. In paint method we should iterate over components in panel and paint its in translated coordinates. 

Final class:

public class ComponentWrapper extends JComponent {
  private JComponent innerComponent;

  public ComponentWrapper(JComponent innerComponent) {
      this.innerComponent = innerComponent;
  }

  @Override
  public void paint(Graphics g) {

      if (innerComponent instanceof JPanel) {
          for (Component comp : innerComponent.getComponents()) {
              Graphics gnew = g.create();
              Point location = comp.getLocation();
              gnew.translate((int)location.getX(), (int)location.getY());
             comp.paint(gnew);

         }
      } else innerComponent.paint(g);
  }
   
  @Override
  public void setMaximumSize(Dimension maximumSize) {
      super.setMaximumSize(maximumSize);
      innerComponent.setMaximumSize(maximumSize);

      innerComponent.doLayout();
  }

  @Override
  public void setMinimumSize(Dimension minimumSize) {
      super.setMinimumSize(minimumSize);
      innerComponent.setMinimumSize(minimumSize);

      innerComponent.doLayout();
  }

  @Override
  public void setPreferredSize(Dimension preferredSize) {
      super.setPreferredSize(preferredSize);
      innerComponent.setPreferredSize(preferredSize);

      innerComponent.doLayout();
  }

  @Override
  public void setBounds(Rectangle r) {
      super.setBounds(r);
      innerComponent.setBounds(r);

      innerComponent.doLayout();
  }

  @Override
  public void setBounds(int x, int y, int width, int height) {
      super.setBounds(x, y, width, height);
      innerComponent.setBounds(x, y, width, height);

      innerComponent.doLayout();
  }

  @Override
  public void setSize(int width, int height) {
      super.setSize(width, height);
      innerComponent.setSize(width, height);

      innerComponent.doLayout();
  }
}

P.S.(Intro to my blog): Hi all, I hope that my tips help you. But my English is very bad and I want to do it better. If you can, correct me in comments, please.

Most popular

Authors