Previously you could add WTP to your profile. But now, WTP is no longer listed in the catalog and there is no way to add it to a profile. Instead, you must start with the Java EE profile (which BTW also brings in Mylyn and Data Tools). I learnt this the hard way, after I browsed through the catalog and installed my custom profile and later found out that the HTML editor was missing!
Friday, July 24, 2009
Eclipse WTP missing in Pulse Catalog
If you use pulse to manage your local eclipse installation (if not, you should check it out) the Galileo profiles are slightly different from Ganymede.
Tuesday, January 27, 2009
Bash command completion
If you cannot live without command completion in the linux shell, check this out...you can even get completion working for command arguments!! I was pretty thrilled to learn about this.
See the debian documentation for details. In Ubuntu Hardy, the /etc/bash_completion that provides this functionality is missing. You can download this missing file from here. I extracted it from the source.
Tuesday, October 28, 2008
One reason a Rails application breaks with no error message
I'm new to Ruby and Rails and spent about 3 hours trying to figure out why objects of my Purchase model which references my Transaction model weren't being presisted. Rails would say that the object was saved in the database but there were no records being created. Also Rails wouldn't throw any error message either.
After pulling hair for 3 hours I nailed it down to my Transaction model. Apparently Transaction is a reserved keyword in Rails. So once I renamed my Transaction model to Receipt things worked like a breeze.
Here is the list of keywords that will save me from going bald the next time:
http://wiki.rubyonrails.org/rails/pages/ReservedWords
Now, I wonder why Rails doesn't detect the use of a reserved keyword and throw an explicit error instead of not only failing silently but also telling me that things are huky-dory!!?
After pulling hair for 3 hours I nailed it down to my Transaction model. Apparently Transaction is a reserved keyword in Rails. So once I renamed my Transaction model to Receipt things worked like a breeze.
Here is the list of keywords that will save me from going bald the next time:
http://wiki.rubyonrails.org/rails/pages/ReservedWords
Now, I wonder why Rails doesn't detect the use of a reserved keyword and throw an explicit error instead of not only failing silently but also telling me that things are huky-dory!!?
Wednesday, November 7, 2007
Log4j and MySQL
When configuring log4j with an appender to log to a MySQL database there are some nuances you might need to be aware of.
First, here is what the relevant settings in the log4j.properties file should look like:
# Set root logger level to DEBUG and its only appender to DB.
log4j.rootLogger=DEBUG, DB
# The database logger
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:mysql://myserver:3306/mydb?autoReconnect=true
log4j.appender.DB.driver=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
log4j.appender.DB.user=myuser
log4j.appender.DB.password=mypassword
log4j.appender.DB.sql=INSERT INTO mytable (mycolmn) VALUES ("%m")
Two things to note:
http://forum.java.sun.com/thread.jspa?threadID=5227993&tstart=105
First, here is what the relevant settings in the log4j.properties file should look like:
# Set root logger level to DEBUG and its only appender to DB.
log4j.rootLogger=DEBUG, DB
# The database logger
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:mysql://myserver:3306/mydb?autoReconnect=true
log4j.appender.DB.driver=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
log4j.appender.DB.user=myuser
log4j.appender.DB.password=mypassword
log4j.appender.DB.sql=INSERT INTO mytable (mycolmn) VALUES ("%m")
Two things to note:
- I had to specify the driver property because log4j couldn't automatically determine that or was defaulting to an incorrect driver class name. I was using log4j 1.2.12 and MySQL Connector/J version 5.1.5
- The values being inserted in the database need to be enclosed in double quotes (") as opposed to the normal single quote (') you would use in SQL syntax
http://forum.java.sun.com/thread.jspa?threadID=5227993&tstart=105
Tuesday, October 30, 2007
Hello World! REST web service using Jersey and Glassfish
Recently I had the need to expose some EJB application functionality to a client PHP application. I wanted to avoid the heavy weight SOAP protocol and REST seemed like a good choice. Wanting to stay within the JAVA language for a more seamless developer experience I came across the JSR 311 spec and the implementation Jersey.
If you are a JAVA programmer and are wanting to use REST in your architecture you might want to investigate Jersey. Most of the Jersey documentation on the web is using Netbeans. I wanted to use Eclipse since that is my primary IDE. So a short post on the Jersey Users mailing list elicited some quick responses with clear instructions on how to use Jersey outside of an IDE.
Here's step by step instruction on how to implement a Hello World REST Web Service. This post assumes that you are using Eclipse with the Maven 2 plugin and using Glassfish V2 and Jersey 0.4-ea release. Jersey is still an evolving spec and so these steps might very well change in the future.
First download Jersey and unzip the file. The 0.4-ea version of the Jersey libraries are not available on the maven site though the older versions are. So you have to install the Jersey libraries (jersey.jar, jsr311-api.jar, jettison-1.0-RC1.jar) into a local maven repository.
Create a new Maven2 project called restapp in Eclipse with the following folder structure
src/main/java
src/main/webapp
src/main/webapp/WEB-INF
Edit the maven pom.xml file so it looks something like below:
<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xsi=\"http://www.w3.org/2001/XMLSchema-instance\" schemalocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">
<modelversion>4.0.0</modelversion>
<groupId>restapp</groupId>
<artifactId>restapp</artifactId>
<packaging>war</packaging>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<artifactid>maven-compiler-plugin</artifactid>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactid>maven-source-plugin</artifactid>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>MyMavenRepo</id>
<name>MyMavenRepo</name>
<url>http://myserver/maven</url>
</repository>
<repository>
<id>Ibiblio</id>
<name>Ibiblio</name>
<url>http://www.ibiblio.org/maven</url>
</repository>
<repository>
<id>java.net</id>
<url>
https://maven-repository.dev.java.net/nonav/repository
</url>
<layout>legacy</layout>
</repository>
</repositories>
<dependencies>
<dependency>
<groupid>net.sf.json-lib</groupid>
<artifactid>json-lib</artifactid>
<version>0.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>javax.ejb</groupid>
<artifactid>ejb-api</artifactid>
<version>3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>javax.j2ee</groupid>
<artifactid>j2ee</artifactid>
<version>1.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>jersey</groupid>
<artifactid>jersey</artifactid>
<version>0.4-ea</version>
</dependency>
<dependency>
<groupid>javax.ws.rs</groupid>
<artifactid>jsr311-api</artifactid>
<version>0.4-ea</version>
</dependency>
<dependency>
<groupid>org.codehaus.jettison</groupid>
<artifactid>jettison</artifactid>
<version>1.0-RC1</version>
</dependency>
<dependency>
<groupid>rome</groupid>
<artifactid>rome</artifactid>
<version>0.8</version>
</dependency>
</dependencies>
</project>
Depending on how you installed the downloaded Jersey libraries into your local repository you might have to fix the pom.xml correctly. Also you might not need some of the other libraries I've listed in the pom.xml. I had them anyway because I needed those to make some EJB lookups.
Create a new file web.xml in the src/main/webapp/WEB-INF folder with the following contents
<web-app>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>
com.sun.ws.rest.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>webresourceclass</param-name>
<param-value>
rest.resources.RootResources
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Create a Java class called rest.resources.RootResources.java in src/main/java. This class should match the webresourceclass parameter value in the web.xml.
The RootResources.java class should like below:
package rest.resources;
import com.sun.ws.rest.api.core.DefaultResourceConfig;
public class RootResources extends DefaultResourceConfig {
public RootResources() {
super(HelloResource.class);
}
}
Now create the rest.resource.HelloResource.java as below:
package rest.resources;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.UriParam;
import javax.ws.rs.UriTemplate;
// The Java class will be hosted at the URI path "/helloworld"
@UriTemplate("/helloworld")
public class HelloResource {
@HttpMethod("GET")
@ProduceMime("text/plain")
public String sayHello() {
return "Hello World!";
}
}
Now execute the mvn clean package command to package the app as a war. You can deploy the war into Glassfish via the admin console or the autodeploy folder. Make sure there are no deployment error messages logged in the Glassfish server.log file.
Fire up your browser and visit http://localhost:8080/restapp-1.0.0/helloworld to REST easy :)
If you are a JAVA programmer and are wanting to use REST in your architecture you might want to investigate Jersey. Most of the Jersey documentation on the web is using Netbeans. I wanted to use Eclipse since that is my primary IDE. So a short post on the Jersey Users mailing list elicited some quick responses with clear instructions on how to use Jersey outside of an IDE.
Here's step by step instruction on how to implement a Hello World REST Web Service. This post assumes that you are using Eclipse with the Maven 2 plugin and using Glassfish V2 and Jersey 0.4-ea release. Jersey is still an evolving spec and so these steps might very well change in the future.
First download Jersey and unzip the file. The 0.4-ea version of the Jersey libraries are not available on the maven site though the older versions are. So you have to install the Jersey libraries (jersey.jar, jsr311-api.jar, jettison-1.0-RC1.jar) into a local maven repository.
Create a new Maven2 project called restapp in Eclipse with the following folder structure
src/main/java
src/main/webapp
src/main/webapp/WEB-INF
Edit the maven pom.xml file so it looks something like below:
<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xsi=\"http://www.w3.org/2001/XMLSchema-instance\" schemalocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">
<modelversion>4.0.0</modelversion>
<groupId>restapp</groupId>
<artifactId>restapp</artifactId>
<packaging>war</packaging>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<artifactid>maven-compiler-plugin</artifactid>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactid>maven-source-plugin</artifactid>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>MyMavenRepo</id>
<name>MyMavenRepo</name>
<url>http://myserver/maven</url>
</repository>
<repository>
<id>Ibiblio</id>
<name>Ibiblio</name>
<url>http://www.ibiblio.org/maven</url>
</repository>
<repository>
<id>java.net</id>
<url>
https://maven-repository.dev.java.net/nonav/repository
</url>
<layout>legacy</layout>
</repository>
</repositories>
<dependencies>
<dependency>
<groupid>net.sf.json-lib</groupid>
<artifactid>json-lib</artifactid>
<version>0.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>javax.ejb</groupid>
<artifactid>ejb-api</artifactid>
<version>3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>javax.j2ee</groupid>
<artifactid>j2ee</artifactid>
<version>1.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>jersey</groupid>
<artifactid>jersey</artifactid>
<version>0.4-ea</version>
</dependency>
<dependency>
<groupid>javax.ws.rs</groupid>
<artifactid>jsr311-api</artifactid>
<version>0.4-ea</version>
</dependency>
<dependency>
<groupid>org.codehaus.jettison</groupid>
<artifactid>jettison</artifactid>
<version>1.0-RC1</version>
</dependency>
<dependency>
<groupid>rome</groupid>
<artifactid>rome</artifactid>
<version>0.8</version>
</dependency>
</dependencies>
</project>
Depending on how you installed the downloaded Jersey libraries into your local repository you might have to fix the pom.xml correctly. Also you might not need some of the other libraries I've listed in the pom.xml. I had them anyway because I needed those to make some EJB lookups.
Create a new file web.xml in the src/main/webapp/WEB-INF folder with the following contents
<web-app>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>
com.sun.ws.rest.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>webresourceclass</param-name>
<param-value>
rest.resources.RootResources
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Create a Java class called rest.resources.RootResources.java in src/main/java. This class should match the webresourceclass parameter value in the web.xml.
The RootResources.java class should like below:
package rest.resources;
import com.sun.ws.rest.api.core.DefaultResourceConfig;
public class RootResources extends DefaultResourceConfig {
public RootResources() {
super(HelloResource.class);
}
}
Now create the rest.resource.HelloResource.java as below:
package rest.resources;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.UriParam;
import javax.ws.rs.UriTemplate;
// The Java class will be hosted at the URI path "/helloworld"
@UriTemplate("/helloworld")
public class HelloResource {
@HttpMethod("GET")
@ProduceMime("text/plain")
public String sayHello() {
return "Hello World!";
}
}
Now execute the mvn clean package command to package the app as a war. You can deploy the war into Glassfish via the admin console or the autodeploy folder. Make sure there are no deployment error messages logged in the Glassfish server.log file.
Fire up your browser and visit http://localhost:8080/restapp-1.0.0/helloworld to REST easy :)
Friday, October 26, 2007
Programmatic Login to Authenticate Against a EJB in Glassfish
What?
This is the method used to authenticate a standalone java client (including Eclipse RCP plugins) to the Glassfish EJB container.
References
How?
See here on how to configure Glassfish's server.policy file: https://glassfish.dev.java.net/javaee5/docs/DG/beabg.html#beacm
Make sure the following jars from Glassfish are in the classpath:
The following parameter needs to be passed the VM
-Djava.security.auth.login.config=/appclientlogin.conf
where PATH is the fully qualified path to the appclientlogin.conf. You can get this file from your glassfish installation. This file should be shipped with your client code.
Edit the appclientlogin.conf to add the following
file {
com.sun.enterprise.security.auth.login.ClientPasswordLoginModule required debug=true;
};
where "file" is the realm name you have configured in Glassfish. By default glassfish comes with the file realm pre-configured. See [here|http://weblogs.java.net/blog/tchangu/archive/2007/01/ldap_security_r.html] for instructions on how to configure an LDAP realm.
Now, add the following code to your client to authenticate a bean:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
// NOTE: IIOP is set on port 3701 but this works on port 3700
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
// props.setProperty("java.security.auth.login.config", "");
ProgrammaticLogin programmaticLogin = new ProgrammaticLogin();
try {
Boolean login = programmaticLogin.login("myuser", "password",
"file", false);
// login always returns true
// always uses default realm for some reason
System.out.println("State:" + login);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println();
InitialContext ctx;
try {
ctx = new InitialContext(props);
// this is where the actual login happens!
serviceBean = (PermitServiceRemote) ctx
.lookup("ejb/permit/stateless/PermitServiceBean");
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
You should be set. For some of discussions surrounding this see here:
This is the method used to authenticate a standalone java client (including Eclipse RCP plugins) to the Glassfish EJB container.
References
- http://java.sun.com/developer/EJTechTips/2006/tt0225.html#2
How?
See here on how to configure Glassfish's server.policy file: https://glassfish.dev.java.net/javaee5/docs/DG/beabg.html#beacm
Make sure the following jars from Glassfish are in the classpath:
- javaee.jar
- appserv-admin.jar
- appserv-deployment-client.jar
- appserv-ext.jar
- appserv-rt.jar
- and your client classes with the EJB lookup code
The following parameter needs to be passed the VM
-Djava.security.auth.login.config=
where PATH is the fully qualified path to the appclientlogin.conf. You can get this file from your glassfish installation. This file should be shipped with your client code.
Edit the appclientlogin.conf to add the following
file {
com.sun.enterprise.security.auth.login.ClientPasswordLoginModule required debug=true;
};
where "file" is the realm name you have configured in Glassfish. By default glassfish comes with the file realm pre-configured. See [here|http://weblogs.java.net/blog/tchangu/archive/2007/01/ldap_security_r.html] for instructions on how to configure an LDAP realm.
Now, add the following code to your client to authenticate a bean:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
// NOTE: IIOP is set on port 3701 but this works on port 3700
props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
// props.setProperty("java.security.auth.login.config", "");
ProgrammaticLogin programmaticLogin = new ProgrammaticLogin();
try {
Boolean login = programmaticLogin.login("myuser", "password",
"file", false);
// login always returns true
// always uses default realm for some reason
System.out.println("State:" + login);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println();
InitialContext ctx;
try {
ctx = new InitialContext(props);
// this is where the actual login happens!
serviceBean = (PermitServiceRemote) ctx
.lookup("ejb/permit/stateless/PermitServiceBean");
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
You should be set. For some of discussions surrounding this see here:
- http://fisheye5.cenqua.com/browse/glassfish/appserv-core/src/java/com/sun/appserv/security/ProgrammaticLogin.java?r=1.5
- http://forums.java.net/jive/thread.jspa?messageID=242260𻉔
- http://forum.java.sun.com/thread.jspa?threadID=761291&tstart=255
- https://glassfish.dev.java.net/javaee5/docs/DG/beabg.html#beacm
Subscribe to:
Posts (Atom)