Tuesday, August 31, 2010

Apache Wicket

in May I came across Apache Wicket
and I really became a big fan of this framework
in a very short time I was able to rewrite a web application based on another (JSF-based) framework by following the examples from

Wicket in Action
by Martijn Dashorst and Eelco Hillenius

What I found difficult was the migration from the already implemented web application from Wicket 1.3.1 to Wicket 1.4.8

here are some notes I took back then

1) instead of MarkupContainer use WebMarkupContainer (Form.add() does not accept MarkupContainer as an argument)
2) wicket configuration web.xml -> wicket.configuration
3) instead of getModel() and setModel(), getDefaultModel() and setDefaultModel() to be used
4) messages are not displayed -> FeedbackPanel has to be inherited
5) validation -> ListView -> text fields into ListItem
6) Error Page

(why I rewrote the web application - I didn't have this planned, although I didn't like its performance... it always amazes me how a specification, in this case JSF is turned into an implementation, in this case Woodstock and then ICEFaces...)
so, I just started evaluating wicket rewriting a web application that is small from one hand and known to me on other hand. I liked so much wicket, so what was started just an evaluation project, became a replacement of the original implementation. the performance is just great.... and not just that ... it is very pleasant to use wicket !)

Socket Connections over HTTPS

//simple proof-of-the-concept and connection test 2010-07-22
//assumption - certificate already loaded in cacerts file
//@see also java web service security post

package com.yourhost.socket.client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.security.KeyStore;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;


public class GB_GRIPSMXWS_SocketClient {

public static final String SOCKET_SERVER_HOST = "www.yourhost.com";
public static int SOCKET_SERVER_PORT = 443;
int timeout = 10000;

/**
* @param args
*/
public static void main(String[] args) {

try {

int port = SOCKET_SERVER_HOST;
String hostname = SOCKET_SERVER_PORT;

char[] passphrase = "changeit".toCharArray();

File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
context.init(null, new TrustManager[] {defaultTrustManager}, null);
SSLSocketFactory factory = context.getSocketFactory();

System.out.println("Opening connection to " + hostname + ":" + port + "...");
SSLSocket socket = (SSLSocket)factory.createSocket(hostname, port);
socket.setSoTimeout(timeout);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
System.out.println();
System.out.println("No errors, certificate is already trusted");

BufferedWriter writer =
new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
BufferedReader reader =
new BufferedReader(new InputStreamReader(
socket.getInputStream()));

// write reply to the output
//hidden -> serialize XML message to the writer
writer.write("");
writer.write("
");
writer.write("OperationName");
writer.write("2009-08-08T09:59:24.854725+01:00");
writer.write("");
writer.write("SenderID");
writer.write("");
writer.write("");
writer.write("");
writer.write("
");
writer.write("
");
writer.write("
");
writer.write("");
//so on
writer.write("
");
writer.write("
");
writer.flush();





String messageLine = null;
while ((messageLine=reader.readLine())!= null) {
System.out.println(messageLine);
}

reader.close();
writer.close();

socket.close();
} catch (SSLException ex) {
System.out.println();
ex.printStackTrace(System.out);
}



} catch (Exception ex) {
ex.printStackTrace();
}
}

}

metro (JAX-WS) web service life cycle

annotations are used (in your Service Implementation Bean)
@PostConstruct
@PreDestroy

(in JAX-RPC java.xml.rpc.server.ServiceLifecycle interface implementation was used for this purpose)

favourite tools

Allround Automations - PL/SQL Developer
Sparks Enterprise Architect
Altova XML Spy
Araxis Merge
eviware soapUI

German-English glossary, Automobile Industry

immer wieder tauchen die gleichen Begriffe auf, naemlich...

Bremsflüssigkeit - brake fluid
Siedepunkt - boiling point
HBA (d.h. Hifsbremseabbremsung) - emergency brake deceleration
KKM-Stand(die) - kilometer reading / odometer reading ?

Friday, August 27, 2010

metro books and resources

Java Web Services: Up and Running
by Martin Kalin
http://oreilly.com/catalog/9780596521134


Title:
Java Web Services: Up and Running
By:
Martin Kalin
Publisher:
O'Reilly Media
Formats:

* Print
* Ebook
* Safari Books Online

Print Release:
February 2009
Ebook Release:
February 2009
Pages:
320
Print ISBN:
978-0-596-52112-7
| ISBN 10:
0-596-52112-X
Ebook ISBN:
978-0-596-80125-0
| ISBN 10:
0-596-80125-4

metro web services - useful links

http://www.javaworld.com/community/node/981

Thursday, August 26, 2010

metro web services

installed JDK 1.6.0.21
metro 2.1

top down approach i.e. starting from WSDL

0. assumption
you have (prepared) WSDL

1.
starting wsimport I get an error message saying that JAX-WS2.2 is required while JAX-WS2.1 is actually available; suggestion either to use -Xendorsed
other solution - to put webservices-api.jar from metro/lib to endorsed lib
(it is interesting that system variable java.endorsed.dirs is not taken into account. endorsed lib in java_home\jre\lib is working though

other problems met
definitions of faults in WSDL

wsimport generates Service Endpoint Interface aka SEI e.g.
@WebService(name = "GRIPSMX", targetNamespace = "http://jetsystems.com/GRIPSMX/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
ObjectFactory.class
})

2.
to implement it - create a class that implements the interface
(so called Service Implementation Bean aka SIB)
with annotation
@WebService(endpointInterface = "com.jetsystems.gripsmx.GRIPSMX")
and implement the actual web service methods

3. deployment

see
https://jax-ws.dev.java.net/guide/Deploying_Metro_endpoint.html
Deployment Metro Endpoint


a jax-ws web service is deployed as a separate web application with following stucture
WEB-INF/classes/ containing service endpoint interface (SEI) and SIB
WEB-INF/sun-jaxws.xml JAX-WS RI deployment descriptor
WEB-INF/web.xml Web deployment descriptor
WEB-INF/wsdl/[subdir with a name = of SIB]/ WSDL and XSD

e.g.
GRIPSMX/WEB-INF/classes/
GRIPSMX/WEB-INF/sun-jaxws.xml
GRIPSMX/WEB-INF/web.xml
GRIPSMX/WEB-INF/wsdl/GRIPSMXImplementation/GRIPSMX.wsdl
GRIPSMX/WEB-INF/wsdl/GRIPSMXImplementation/GRIPSMX.xsd

e.g. sun-jaxws.xml

<?xml version="1.0" encoding="UTF-8"?>
<endpoints version="2.0" xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime">
<endpoint implementation="com.jetsystems.gripsmx.GRIPSMXImplementation" name="GRIPSMX" url-pattern="/GRIPSMX"/>
</endpoints>

and web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>GRIPSMX</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>GRIPSMX</servlet-name>
<url-pattern>/GRIPSMX</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

where url-pattern in sun-jaxws.xml must match url-pattern in web.xml

http://localhost:8080/GRIPSMX/GRIPSMX?wsdl

Wednesday, August 25, 2010

ant javac

by default without line numbers
to switch it on e.g.

debug="true" debuglevel="lines,vars,source"

Hibernate and Tomcat Database Connection Pooling

1. Tomcat Database Connection Pooling (should have been an older post)
usage in a web application

1a. define db connection in context.xml in META-INF

e.g.
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/gripswsmx-hibernated">
<Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver" maxActive="20" maxIdle="10" maxWait="-1" name="jdbc/GRIPSHI" password="gripshi" type="javax.sql.DataSource" url="jdbc:oracle:thin:@192.168.2.94:1521:ORCL" username="gripshi" validationQuery="select 1 from dual"/>
</Context>

note that Context path must correspond to the web application name
validationQuery is vital to keep the connection alive

once deployed this file is moved to catalina conf/Catalina/localhost under the name of the web application / context path - so, if there are changes in db connection this file has to be edited (to avoid a new deployment)

1b. in web.xml define the connection name e.g. jdbc/GRIPSHI

<resource-ref>
<description>GRIPS MX web service DataSource Reference</description>
<res-ref-name>jdbc/GRIPSHI</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

2. Hibernate
in hibernate.properties or in hibernate.cfg.xml
2a) specify properties
hibernate.dialect
hibernate.connection.datasource pointing to the name specified in web.xml

e.g. in hibernate.cfg.xml
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.connection.datasource">java:comp/env/jdbc/GRIPSHI</property>

2b) make sure the rest of hibernate properties for db connection
i.e.
hibernate.connection.driver_class
hibernate.default_schema
hibernate.connection.url
hibernate.connection.username
hibernate.connection.password
are omitted


see also Using Hibernate with Tomcat - C3P0 connection pool

Wednesday, August 4, 2010

Hibernate Tools

eclipse plugin
https://www.jboss.org/tools/download/stable.html

for eclipse Ganymede 3.4 - this release
https://www.jboss.org/tools/download/stable/3_0_GA.html
add site - http://download.jboss.org/jbosstools/updates/JBossTools-3.0.3.GA/

for Eclipse Helios 3.6. - 3.1. release - asks for another plugin

soapUI - parametrized tests

my goal was parametrized load tests - because of the data validation done by the web service it is not possible to run the same tests over and over again

some web sites

http://stackoverflow.com/questions/945403/soapui-getting-request-parameters-in-mock-service-script

http://www.soapui.org/Functional-Testing/working-with-scripts.html

http://groovyinsoapui.wordpress.com/2008/09/30/load-testing-with-soap-request-having-variable-parameters/

http://soa.dzone.com/articles/functional-web-services-1?page=0,5

was I accomplish was not much but:

1. TestSuite -> Test Case -> new Test Step 'Properties' - moved to the first place
defined new parameters:

receiptDateStr date e.g. 2010-08-04
receiptNumber numer e.g. 1

2. TestSuite -> Test Case -> Test Case Editor -> Setup Script added script that initialize the properties values:


log.info("In the Test Case IssueCheque Setup Script")
today = new Date()
sdf = new java.text.SimpleDateFormat("yyyy-MM-dd")
receiptDate = sdf.format(today)
log.info("In the Test Test Case IssueCheque Setup Script: receiptDate = " + receiptDate)

targetStep = testRunner.testCase.getTestStepByName( "Properties" )
// transfer all properties
targetStep.setPropertyValue( "receiptDateStr", receiptDate)

receiptNumber = Integer.valueOf(targetStep.getPropertyValue("receiptNumber"))
log.info("In the Test Test Case IssueCheque Setup Script: last receiptNumber = " + receiptNumber)
receiptNumber = receiptNumber + 1
log.info("In the Test Test Case IssueCheque Setup Script: current receiptNumber = " + receiptNumber)
targetStep.setPropertyValue( "receiptNumber", String.valueOf(receiptNumber))

log.info(receiptDate)

3. In the test case IssueCheque that follows Properties I replaced actual values with parameters referecences:

${Properties#receiptNumber}
${Properties#receiptDateStr}

Monday, August 2, 2010

readonly attribute of a folder on XP

http://support.microsoft.com/?id=326549