Search This Blog

Friday, February 24, 2012

Quick ref of managed Beans config in Spring

Within your service


@ManagedResource
(objectName="bean:name=SampleService",
description="Properties Service", log=true)
public class SampleImpl implements ISampleService

      @ManagedAttribute
      public void setName(String name) {
            ...
      }


Within your startup of your weblogic or whatever app container

 
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8088
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false



Startup jconsole and enter the hostname and the port within the "Remote Process" field.

done.


The full address to the remote process is

service:jmx:rmi:///jndi/rmi://SERVERNAME:PORT/jmxrmi



Thursday, February 9, 2012

Buffered File writing Snip

        byte[] content  = "Content is overrated".getBytes();
        String filename = "C:/temp/hirsch." + lieferung.getFormat();
        BufferedOutputStream bos = null;
        try {
            FileOutputStream fos = new FileOutputStream(new File(filename));
            bos = new BufferedOutputStream(fos);
            bos.write(content);
        } catch (Exception e) {
            LOG.error("Write Exception" , e);
        } finally {
            if (bos != null) {
                try {
                    bos.flush();
                    bos.close();
                } catch (Exception e) {
                    LOG.error("Close or Flush Exception" , e);
                }
            }
        }

Thursday, January 26, 2012

Database table history with triggers

Here is a short sample about keeping all data of a table within a history table. The way I prefer it to do is via database triggers. Lets assume you have a table called:

CREATE TABLE BOOK {
  • BOOK_ID       NUMBER(10),
  • NAME             VARCHAR2(10),
  • AUTHOR         VARCHAR2(10),
  • ISBN                VARCHAR2(13)
}

Your application as well as your database scripts are working on that table. Your aim is to keep track on all changes on that table. To do so you need a history table, which looks pretty much the same as the original table and you have to add to fields to your original table:

CREATE TABLE BOOK {
  • BOOK_ID                NUMBER(10),
  • NAME                      VARCHAR2(10),
  • AUTHOR                  VARCHAR2(10),
  • ISBN                         VARCHAR2(13)
  • CHANGE_DATE      DATE,
  • CHANGE_USER      VARCHAR2(20)
}

CREATE TABLE BOOK_HISTORY {
  • BOOK_ID                NUMBER(10),
  • NAME                      VARCHAR2(10),
  • AUTHOR                  VARCHAR2(10),
  • ISBN                         VARCHAR2(13)
  • CHANGE_DATE      DATE,
  • CHANGE_USER      VARCHAR2(20),
  • ACTION                   VARCHAR2(100)
}
and create db triggers for all manipulations to the original table:

CREATE OR REPLACE TRIGGER BOOK_INSERT
       BEFORE INSERT ON BOOK
       FOR EACH ROW
BEGIN
   INSERT INTO BOOK_HISTORY
                    (BOOK_ID, NAME, AUTHOR, ISBN, 
                     CHANGE_DATE, CHANGE_USER, ACTION)
    VALUES (:new.BOOK_ID,:new.NAME, :new.AUTHOR, :new.ISBN, 
                      :new.CHANGE_DATE, :new.CHANGE_USER, 'INSERTED');
 END;


CREATE OR REPLACE TRIGGER BOOK_CHANGE
       BEFORE UPDATE ON BOOK
       FOR EACH ROW
BEGIN
   INSERT INTO BOOK_HISTORY
                    (BOOK_ID, NAME, AUTHOR, ISBN, 
                     CHANGE_DATE, CHANGE_USER, ACTION)
    VALUES (:old.BOOK_ID, :old.NAME, :old.AUTHOR, :old.ISBN, 
                      :old.CHANGE_DATE, :old.CHANGE_USER, 'CHANGED');
 END;

CREATE OR REPLACE TRIGGER BOOK_DELETE
       BEFORE DELETE ON BOOK
       FOR EACH ROW
BEGIN
   INSERT INTO BOOK_HISTORY
                    (BOOK_ID, NAME, AUTHOR, ISBN, 
                     CHANGE_DATE, CHANGE_USER, ACTION)
    VALUES (:old.BOOK_ID, :old.NAME, :old.AUTHOR, :old.ISBN, 
                      :old.CHANGE_DATE, :old.CHANGE_USER, 'DELETED');
 END;


These are three simple triggers which will fire if someone (application, scripts or whatever) will change the book table. You might write more sophisticated triggers like WHERE clauses or a CHANGE_FIELD and CHANGE_VALUE column.

Thursday, August 25, 2011

Spring Source Tool STS 2.7.1 and Grails

There are several pitfall you can win if you start using STS behind a proxy. Here is my shit list :-)

Install Groovy and Grails support in STS
After downloading STS 2.7 most of us would try to install the Grails and Groovy Support on the Extension tab of the STS. This will fail if you are behind a proxy. They claim to fix it in later versions. Till then just do the following:
  1. Adjust your network settings within the STS Window->Prefs->network according to your proxy

  2. Go to Help->Install New Software and http://download.eclipse.org/mylyn/snapshots/3.6 as a new site

  3. Install the MyLyn Task List Feature

  4. Restart

you should now be able to use the extension tab.

Install Grails plugins
If you try to install Grails plugins behind a proxy or firewall i.e. like

grails install-plugin calendar
 
you might get an error. To workaround this set the Proxy settings for grails 
within the  ProxySettings.groovy wihtin your .grails folder in your home dir. 
Or you go the grails command line way like that:
grails add-proxy aproxy "--host=myproxy.de" "--port=8008" "--username=myusername" "--password=mypassword" 
grails set-proxy aproxy 
 
That should create a valid ProxySettings.groovy and activate the proxy. 
Even the STS integrated Grails plugin manager should work now.
 
 

Tuesday, August 9, 2011

WinMerge Filter for Java and SVN

## This is a directory/file filter for WinMerge
name: Java and SVN
desc: Suppresses various binaries found in JAVA and svn source trees
## Ignore Java bin files
f: \.class$
f: \.jar$

## Ignore subversion folders
d: \\.svn$
d: \\._svn$


Monday, June 27, 2011

java.math.BigDecimal the difference between setScale and round

One pitfall within BigDecimal I guess is the round method within BigDecimal. Lets assume the following code samples:

BigDecimal smallNumber = new BigDecimal("0.01234");
smallNumber.round(new MathContext(2, RoundingMode.HALF_UP)));
Result   = 0.012
smallNumber.setScale(2, RoundingMode.HALF_UP));
Result   = 0.01

BigDecimal number = new BigDecimal("1.01234");
number.round(new MathContext(2, RoundingMode.HALF_UP))); 
Result   = 1.0
number.setScale(2, RoundingMode.HALF_UP));
Result   = 1.01


So calling round with a MathContext of 2 doesn't alway round to a precision of 2 digits overall. It depends on the number you're trying to round. Reading the JDK docs you will find

".... In general the rounding modes and precision setting determine how operations return results with a limited number of digits when the exact result has more digits (perhaps infinitely many in the case of division) than the number of digits returned. First, the total number of digits to return is specified by the MathContext's precision setting; this determines the result's precision. The digit count starts from the leftmost nonzero digit of the exact result. The rounding mode determines how any discarded trailing digits affect the returned result. ..."

Oops, that is something you have to keep in mind when using round within BigDecimal. So if you really want to achieve a "real" rounding operation on a BigDecimal you should use setScale.

Wednesday, June 15, 2011

JOIN ON multiple conditions

If you want to write an sql join on more than one condition you have to keep in mind that the from clause could just have one condition. Example:

SELECT  * FROM person p, accounts a
  LEFT JOIN preferences  pref ON pref.id = p.pref_id AND pref.name = 'glue'

 will fail, but this

SELECT  * FROM person p
  LEFT JOIN preferences  pref ON pref.id = p.pref_id AND pref.name = 'glue'
  LEFT JOIN accounts a   ON a.id = p.account_id AND a.name = 'snoop'

will work.