Tuesday, 22 July 2008

How to remove a windows update

here is how you should proceed to uninstall the an update : (here KB936357 )

  1. Insert you windows XP CD (any version) in your CD Rom drive, boot, use your boot Menu or go into your bios to choose your CD Rom drive as first boot device

  2. Boot on the CD (hit enter to boot on the CD)

  3. If you're using RAID 0 or RAID 1 for your C drive


    1. Hit F6 to specify an additionnal driver when it tells you so in the bottom dark blue line
    2. wait that windows loads all it's stuff
    3. Insert your floppy disk with raid driver on it
    4. hit S
    5. choose all line marked as "Required" (by repeating the S thing many time)
    6. then hit enter to continu normal boot



  4. Hit R to repare an existing window installation
  5. Choose the windows home directory (usually c:\windows but can be different for entreprise installation or nerds PC ;)
  6. enter the windows Administrator password
  7. you get the command line, now, type the following command :



cd $NtUninstallKB936357$/spuninst
batch spuninst.txt


For me it print on the screen the following (approximative, translate from french):


File not found
1 file copied
1 file copied
1 file copied


And it gives the hand back.

I reboot by typing 'exit', and the update has gone.

Sunday, 6 July 2008

Developping with googleMaps everywhere with the same licence id

When you want to use google maps on a website, you need to signup and get a key for the internet domain name that will use google Maps.

When your developing your googleMaps feature, it's not on the production site with the final url. (At least... I hope it's not so ;)
And you may code some google feature for several sites, and all these sites, you often code it on your computer with a local Apache/Php or Tomcat server.

So in you html (jsp, php, asp whatever) page you'll include the following code to have access to the google maps feature.


<!-- google map -->
<script type="text/javascript" src="http://maps.google.com/maps?file=api&v=2&key=A...5g"> </script>


A simple trick, is to request a key for a fake domain here : http://code.google.com/apis/maps/signup.html

Let's say, for "http://toms-projects"

Get the key, put it in your html code, and then edit your etc/hosts file.
(/etc/hosts on linux, c:\windows\system32\drivers\etc\hosts)

and edit the 127.0.0.1 line to

127.0.0.1       localhost toms-projects


As all system, by default, query the /etc/hosts file before making a DNS query,

toms-projects will be located at 127.0.0.1 by the machine dns client, and thus point to your local website.

And google sees the api key used for the toms-projects domain.

And everything works.

Even better,

you may register directly the final domain key, let's say http://mysupersite.com

and edit you /etc/hosts in the same way :

127.0.0.1       localhost mysupersite.com


It will work as well, but beware, as long as you /etc/hosts file will be configured that way, mysupersite.com will be your computer !

Spring Transaction support with JDBCTemplate and Java 1.5 Annotation

Here is quick tutorial to enable transaction in a Spring project using JdbcTemplate and Java 1.5 Annotations.

I'm using Spring 2.5.2, Java 1.6.
(it should work with Spring 1.2 and Java 1.5 too, considering this blog post, which also gives some usefull info for people new to transaction with Spring)

for example , as simply as this :

@Transactional (propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public Intervention createEmptyIntervention(int idRegulation) throws Exception
{
//...jdbc Code
}



Let's begin with the beginning, applicationContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation= "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:crf-irp.properties</value>
</property>
</bean>

<import resource="spring/cache.xml" />
<import resource="spring/dao.xml" />
<import resource="spring/scheduler.xml" />
<import resource="spring/dwr.xml" />
<import resource="spring/services.xml" />
<import resource="spring/servlet.xml" />

<bean id="SecurityService" class="fr.croixrouge.irp.services.authentification.SecurityServiceImpl" autowire="constructor"/>
</beans>


Here, among other things, I include a dao.xml and a services.xml beans definitions files.
dao.xml defines jdbc related things, and, services.xml some beans that use the jdbc things.

Also, I use XML namespace and XSD instead of DTD, because it will be needed after.

Basically, the <beans ... is equivalent to
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>



here is the dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx = "http://www.springframework.org/schema/tx"

xsi:schemaLocation= "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">



<bean id="crfIrpDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" ><value>${jdbc.driver}</value></property>
<property name="url" ><value>${jdbc.url}</value></property>
<property name="username" ><value>${jdbc.username}</value></property>
<property name="password" ><value>${jdbc.password}</value></property>
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="crfIrpDataSource"/>
</bean>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="crfIrpDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="txManager"/>

</beans>


Besides the usual dataSource and JdbcTemplate, I add a transactionManager and the tx:annotation-driven bean.
This last will do the job of examining your beans for annotations.
The transaction Manager is here to actually manage the transaction where tx:annotation-driven tells to do so.
Notice that 1 namespaces and and 2 xsd locations has been addded for the tx namespace prefix.



To be complete, here is the services.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation= "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">


<!--...-->

<bean id="interventionService" class="fr.croixrouge.irp.services.intervention.InterventionServiceImpl" autowire="constructor" />

</beans>




And finally, the code of the service:

package fr.croixrouge.irp.services.intervention;

import java.sql.Types;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import fr.croixrouge.irp.model.monitor.Intervention;
import fr.croixrouge.irp.services.JDBCHelper;

public class InterventionServiceImpl extends JDBCHelper implements InterventionService
{
private JdbcTemplate jdbcTemplate = null;
private static Log logger = LogFactory.getLog(InterventionServiceImpl.class);



public InterventionServiceImpl(JdbcTemplate jdbcTemplate)
{
this.jdbcTemplate = jdbcTemplate;
}



/*...other methods skipped...*/

private final static String queryForCreateEmptyIntervention =
"INSERT INTO `intervention`\n"+
" (`id_dispositif`, `id_origine`, `id_motif`, `id_regulation`, `DH_saisie`, `num_inter`)\n"+
"VALUES\n"+
" ( 0, 0, 0, ?, ?, 0)\n";

@Transactional (propagation=Propagation.REQUIRED, rollbackFor=Exception.class)

public Intervention createEmptyIntervention(int idRegulation) throws Exception
{
Intervention intervention = new Intervention();

intervention.setIdRegulation(idRegulation);
intervention.setDhReception (new Date() );

Object [] os = new Object[]{ intervention.getIdRegulation(), intervention.getDhReception()};
int [] types = new int []{ Types.INTEGER , Types.TIMESTAMP };

jdbcTemplate.update(queryForCreateEmptyIntervention, os, types);

intervention.setIdIntervention (this.getLastInsertedId());

if(logger.isDebugEnabled())
logger.debug("Intervention inserted with id="+intervention.getIdIntervention());

return intervention;
}
/*...other methods skipped...*/

private int getLastInsertedId()
{
return this.getLastInsertedId(jdbcTemplate, "intervention");
}

/* herited from JDBCHelper*/
protected int getLastInsertedId(JdbcTemplate jdbcTemplate, String tableName)
{
return jdbcTemplate.queryForInt("SELECT last_insert_id() from `"
+
tableName
+"` LIMIT 1", null, null);
}
}


I've changed nothing but the Java 1.5 annotation that tells the TransactionManager that a Transaction is mandatory here (Required), and it should rollback on any exception that is derived from java.lang.Exception.

Here, I set up the transaction, in order last_insert_id query can work. Without a transaction, Spring can use a different connection between the insert query and the last_insert_id query, and in that case, this last query would return 0 instead of the last inserted id.

To be sure that your method has been executed within a transaction, put Spring in debug mode, and you should be able to see something like this :

2008-07-06 19:54:18,828 DEBUG [http-8080-Processor25] (DefaultRemoter.java:462) - Exec: MonitorInputIntervention.createEmptyIntervention() Object created,  not stored. id=0
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:346) - Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@139d115]
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:374) - Creating new transaction with name [fr.croixrouge.irp.services.intervention.InterventionService.createEmptyIntervention]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (DataSourceTransactionManager.java:202) - Acquired Connection [jdbc:mysql://localhost/crfirp?autoReconnect=true, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (DataSourceTransactionManager.java:219) - Switching JDBC Connection [jdbc:mysql://localhost/crfirp?autoReconnect=true, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:186) - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] to thread [http-8080-Processor25]
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:261) - Initializing transaction synchronization
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (JdbcTemplate.java:790) - Executing prepared SQL update
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (JdbcTemplate.java:574) - Executing prepared SQL statement [INSERT INTO `intervention`
(`id_dispositif`, `id_origine`, `id_motif`, `id_regulation`, `DH_saisie`, `num_inter`)
VALUES
( 0, 0, 0, ?, ?, 0)
]
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:142) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] bound to thread [http-8080-Processor25]
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:142) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] bound to thread [http-8080-Processor25]
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (StatementCreatorUtils.java:205) - Setting SQL statement parameter value: column index 1, parameter value [2], value class [java.lang.Integer], SQL type 4
2008-07-06 19:54:18,843 DEBUG [http-8080-Processor25] (StatementCreatorUtils.java:205) - Setting SQL statement parameter value: column index 2, parameter value [Sun Jul 06 19:54:18 CEST 2008], value class [java.util.Date], SQL type 93
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (JdbcTemplate.java:800) - SQL update affected 1 rows
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:142) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] bound to thread [http-8080-Processor25]
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (JdbcTemplate.java:639) - Executing prepared SQL query
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (JdbcTemplate.java:574) - Executing prepared SQL statement [SELECT last_insert_id() from `intervention` LIMIT 1]
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:142) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] bound to thread [http-8080-Processor25]
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:142) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] bound to thread [http-8080-Processor25]
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:142) - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] bound to thread [http-8080-Processor25]
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (InterventionServiceImpl.java:152) - Intervention inserted with id=12
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:880) - Triggering beforeCommit synchronization
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:893) - Triggering beforeCompletion synchronization
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:707) - Initiating transaction commit
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (DataSourceTransactionManager.java:259) - Committing JDBC transaction on Connection [jdbc:mysql://localhost/crfirp?autoReconnect=true, UserName=root@localhost, MySQL-AB JDBC Driver]
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:906) - Triggering afterCommit synchronization
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (AbstractPlatformTransactionManager.java:922) - Triggering afterCompletion synchronization
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:315) - Clearing transaction synchronization
2008-07-06 19:54:18,859 DEBUG [http-8080-Processor25] (TransactionSynchronizationManager.java:232) - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@1bef5e8] for key [org.apache.commons.dbcp.BasicDataSource@14189d0] from thread [http-8080-Processor25]
2008-07-06 19:54:18,875 DEBUG [http-8080-Processor25] (DataSourceTransactionManager.java:314) - Releasing JDBC Connection [jdbc:mysql://localhost/crfirp?autoReconnect=true, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction
2008-07-06 19:54:18,875 DEBUG [http-8080-Processor25] (DataSourceUtils.java:312) - Returning JDBC Connection to DataSource