Read all about my race participation here.
Technorati: running runsfm
Read all about my race participation here.
Technorati: running runsfm
Oh gosh, this is exciting!
Thanks Eduardo for the tip!
Technorati: blogs rank bsc hotblog
The jMaki tutorial from SWDP explained the different approaches to load your own data into a jMaki widget. The jMaki widget models have formalized since then and so the code there no longer works. This TOTD explains how a combo box widget in a JSP page gets it data from a bean.
This TOTD uses NetBeans IDE configured with jMaki plugin and GlassFish.
jMaki Framework
" and use all the defaults. Choose GlassFish as the "Server
".index.jsp
" page, drag-and-drop "Dojo Combobox
" in the "Main Content Area
".<jsp:useBean id="itemBean" scope="session" class="server.ItemValueBean" />
<a:widget name="dojo.combobox" value="${itemBean.value}"/>
jsp:useBean
tag instantiates the bean "server.ItemValueBean
" in session scope. a:widget
tag uses ${itemBean.value}
expression to load the data by invoking getValue()
method from the bean.
ItemValueBean
" in the package "server
". Replace the entire generated code with the following:
package server;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class ItemValueBean {
public String getValue() {
JSONArray value = new JSONArray();
for (int i=0; i<2; i++) {
try {
JSONObject item = new JSONObject();
item.put("name", "name" + i);
item.put("label", "label" + i);
value.put(item);
} catch (JSONException ex) {
ex.printStackTrace();
}
}
try {
return jsonArrayToString(value, null);
} catch (JSONException ex) {
ex.printStackTrace();
}
return null;
}
/**
* Converts a JSON Object to an Object Literal
*
*/
public String jsonToObjectLibertal(JSONObject jo, StringBuffer buff) throws JSONException {
if (buff == null)
buff = new StringBuffer("{");
else
buff.append("{");
JSONArray names = jo.names();
for (int l=0; (names != null) && l < names.length(); l++) {
String key = names.getString(l);
String value = null;
if (jo.optJSONObject(key) != null) {
value = key + ":";
buff.append(value);
jsonToObjectLibertal(jo.optJSONObject(key), buff);
} else if (jo.optJSONArray(key) != null) {
value = key + ":";
buff.append(value);
jsonArrayToString(jo.optJSONArray(key), buff);
} else if (jo.optLong(key, -1) != -1) {
value = key + ":" + jo.get(key) + "";
buff.append(value);
} else if (jo.optDouble(key, -1) != -1) {
value = key + ":" + jo.get(key) + "";
buff.append(value);
} else if (jo.opt(key) != null) {
Object obj = jo.opt(key);
if (obj instanceof Boolean) {
value = key + ":" + jo.getBoolean(key) + "";
} else {
value = key + ":" + "'" + jo.get(key) + "'";
}
buff.append(value);
}
if (l < names.length() -1) buff.append(",");
}
buff.append("}");
return buff.toString();
}
public String jsonArrayToString(JSONArray ja, StringBuffer buff) throws JSONException {
if (buff == null)
buff = new StringBuffer("[");
else
buff.append("[");
for (int key=0; (ja != null) && key < ja.length(); key++) {
The
String value = null;
if (ja.optJSONObject(key) != null){
jsonToObjectLibertal(ja.optJSONObject(key), buff);
} else if (ja.optJSONArray(key) != null) {
jsonArrayToString(ja.optJSONArray(key), buff);
} else if (ja.optLong(key, -1) != -1) {
value = ja.get(key) + "";
buff.append(value);
} else if (ja.optDouble(key, -1) != -1) {
value = ja.get(key) + "";
buff.append(value);
} else if (ja.optBoolean(key)) {
value = ja.getBoolean(key) + "";
buff.append(value);
} else if (ja.opt(key) != null) {
Object obj = ja.opt(key);
if (obj instanceof Boolean) {
value = ja.getBoolean(key) + "";
} else {
value = "'" + ja.get(key) + "'";
}
buff.append(value);
}
if (key < ja.length() -1) buff.append(",");
}
buff.append("]");
return buff.toString();
}
} r>getValue
methods contains the logic to generate the business data. In this case, the method generates the data model expected by ComboBox using JSON APIs. This data can very well be generated by creating a Persistence Unit and querying a database using JPA or any other mechanism.
The jsonToObjectLibertal
and jsonArrayToString
methods were originally posted here. These two methods are required because the JSON parser does not allow you to create object literals but only JSON objects. By default these contain key : value pairs where the keys are enclosed in double quotes which does not match with the expected data model.
Another way to populate jMaki widgets with your data (using JPA) is explained here.
Please leave suggestions on other TOTD that you’d like to see. A complete archive is available here.
Technorati: totd jmaki beans glassfish netbeans
If you attended JavaOne 2007 or any other conference afterwards where Metro (JAX-WS + WSIT/Tango) team presented, then you’ve probably seen this demo. The demo shows an Excel 2007 spreadsheet invoking a Secure and Reliable endpoint deployed on GlassFish. Today, I’m announcing the availability of the WSIT endpoint and Excel client code with full instructions to build, deploy and run the sample.
Metro Release Candidate 1 was announced recently and is integrated in GlassFish RC4. You can learn more about .NET interoperability aspects of Metro by watching this deep dive interview or reading this 26-page article. |
The source code for this sample is available in "wsit/wsit/samples/excelclient
" directory. It can be checked out using the command:
cvs -d :pserver:[email protected]:/cvs co wsit/wsit/samples/excelclient
A compressed bundle of the sample is available here.
Running the demo involves an extensive setup for .NET client. Please make sure to review the software requirements before proceeding with the installation.
Try it and send us feedback at or Metro Forum.
Technorati: webservices metro glassfish dotnet .net interoperability netbeans wcf
Doris pointed out that one of my earlier post is not working any more. That entry explained the steps to create a Web application, deployed on GlassFish V2, and contained a jMaki-wrapped Yahoo Data Table widget pulling data from JavaDB using the JPA.
The main reason for this is because jMaki data models have evolved since I wrote the original entry and are now formalized. Here is the delta from the previous entry to make it working:
<%@ page import="java.util.*" %>
<%@ page import="server.Company" %>
<%@ page import="javax.persistence.*" %>
<%
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jmaki-jpaPU");
EntityManager em = emf.createEntityManager();
List<Company> list = em.createQuery("select c from Company c").getResultList();
out.println("{columns : [" +
"{ label : 'Company Name', id : 'companyName'}," +
"{ label :'Price', id : 'price'}," +
"{ label :'Change', id : 'change'}," +
"{ label :'% Change', id : 'pctChange'}," +
"{ label :'Last Updated', id : 'lastUpdated'}" +
"],");
out.println("rows: [");
for (int i=0; i<list.size(); i++) {
Company c = list.get(i);
out.print("{ companyName: '" + c.getCompanyname() + "'," +
"price: '" + c.getPrice() + "'," +
"change: '" + c.getChange() + "'," +
"pctChange: '" + c.getPercentchange() + "'," +
"lastUpdated: '" + c.getLastupdated() + "'}");
if (i < list.size()-1)
out.println(",");
else
out.println();
}
out.println("] }");
%>
<a:widget name="yahoo.dataTable"
service="data.jsp" />
With jMaki 0.9.7.1, here is a snapshot of the updated web page:
And the updated NetBeans project is available here.
Technorati: jmaki glassfish jpa netbeans
ActiveRecord-JDBC 0.5 is now available. As mentioned earlier, one of the main features in this release is simplified database configuration for JRuby-on-Rails applications. From the release notes:
It is no longer necessary to specify :driver and :url configuration parameters for the mysql, postgresql, oracle, derby, hsqldb, and h2 adapters.
This means that if you deploy a Rails application as a WAR file on GlassFish as described here, then there is no need to specify the JDBC adapter, the JDBC driver class name or the database connection URL. The ActiveRecord-JDBC uses the native MySQL adapter to connect directly to the database. And so there is no need to even copy MySQL Connector/J driver JAR file in GlassFish\lib directory.
This means the database configuration
production:
adapter: jdbc
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/helloworld_development
username: root
password:
can now be written as
production:
adapter: mysql
database: HelloWorld_production
username: root
password:
host: localhost
And this is the default configuration generated by Rails app anyway.
This really simplifies the database configuration for deploying Rails applications on GlassFish. As a result the steps described here (bullet 2 & 3), here (bullet 4.2.1 & 4.2.2) and in screencast #web6 (10:52 – 11:56) are not required any more.
I’d like to point out that it’s not necessary to specify this information. But if you have any applications deployed with these settings, they’ll continue to work. Installing the plugin using the standard way (jruby script\plugin install activerecord-jdbc
) will give you the latest version anyway.
I’m particularly excited about this change as it brings C-based Ruby and JRuby applications one step closer to each other.
Tom explained other simplifications.
Technorati: rubyonrails jrubyonglassfish jruby ruby glassfish mysql
jMaki is a light-weight framework for build Web 2.0 applications. It provides support for multiple languages – Java (1, 2, 3, 4, 5, 6) , PHP, Ruby (1, 2), Phobos (1). The numbers in parentheses indicate the entries that I’ve created showing jMaki support for that language. As evident, I’ve not created a single entry for PHP yet. This entry is going to change that
This entry shows how to deploy a jMaki-enabled PHP web application in GlassFish. It builds upon an earlier entry that showed how to deploy a simple PHP application in GlassFish.
jmaki-php-0.9.7.2\jmaki-php
" in the current directory.jmaki-php-0.9.7.2\jmaki-php\core
" and invoke "ant
". This creates "dist\jmaki-core.zip
".jmaki-core.zip
" under the "web
" directory of the project created in the link followed from first step.http://localhost:8080/hellophp/jmaki-core/index.php
".
If you look at "index.php
" in the IDE, the page contains the following code fragments:
<?php addWidget("hello"); ?>
<?php addWidget( array( "name" => "hello2",
"args" => "{name: 'Duke'}")
); ?>
If you look at the source code of the generated page, the PHP code is converted to JavaScript code as shown below:
<link type='text/css' rel='stylesheet' href='http://localhost:8080:8080/hellophp/jmaki-core/resources/hello/component.css'></link>
<script type='text/javascript' src='http://localhost:8080:8080/hellophp/jmaki-core/resources/hello/component.js'></script>
<script type='text/javascript'>
jmaki.addWidget({uuid:"hello_2",
name:"hello",
widgetDir:"http://localhost:8080:8080/hellophp/jmaki/resources/hello",
script:"http://localhost:8080:8080/hellophp/jmaki/resources/hello/component.js"});
</script>
and
<link type='text/css' rel='stylesheet' href='http://localhost:8080:8080/hellophp/jmaki-core/resources/hello2/component.css'></link>
<script type='text/javascript' src='http://localhost:8080:8080/hellophp/jmaki-core/resources/hello2/component.js'></script>
<div id="hello2_3" class="hello2"></div>
<script type='text/javascript'>
jmaki.addWidget({uuid:"hello2_3",
name:"hello2",
widgetDir:"http://localhost:8080:8080/hellophp/jmaki-core/resources/hello2",
args: {name: 'Duke'},
script:"http://localhost:8080:8080/hellophp/jmaki-core/resources/hello2/component.js"});
</script>
Notice the JavaScript code shows the host + port as "localhost:8080:8080
". This issue is followed here.
jmaki-php-0.9.7.2\jmaki-php\samples\loadtable
" and invoke "ant
". This creates "dist\jmaki-loadtable-php-0.9.7.2.zip
".web
" directory of your project.http://localhost:8080/hellophp/web/jmaki-loadtable/index.php
".
This sample shows a Dojo DataTable loading static data. The code fragment to add the widget to the page is:
<?php
addWidget('dojo.table', null, null, null, "tabledata.json");
?>
You can look at the generated source using "View Source". A nice twi
st to try is to dynamically load the data from a database using JPA as shown here.
None of the samples that use XMLHttpProxy (rssData, cl-mashup and mapit) will work because I could not find XSLT extension for Quercus. This issue is followed here. Other users have asked similar question with no clear answer.
Technorati: jmaki php glassfish web2.0 caucho quercus
Quercus is Caucho Technology’s 100% Java implementation of PHP 5. Ludo described the steps to deploy PHP web applications on GlassFish. Caucho has released a new version of Quercus since then. This blog entry is an update to the steps described earlier.
WEB-INF/lib
" directory to "GLASSFISH_HOME/domains/domain/lib
" directory. That’s it! Although the original entry requires to copy the JARs in "GLASSFISH_HOME/lib/addons
" directory but that didn’t work.hellophp
", using NetBeans IDE and choose GlassFish as the server.<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
version="2.5">
<description>Caucho Technology's PHP Implementation, Running on GlassFish Java EE 5</description>
<servlet>
<servlet-name>Quercus Servlet</servlet-name>
<servlet-class>com.caucho.quercus.servlet.QuercusServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Quercus Servlet</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.php</welcome-file>
</welcome-file-list>
</web-app>
This will declare PHP engine as the servlet.
index.php
" in "Web pages
" folder. The contents of the page are:
<?php
echo "Hello World!";
phpinfo();
?>
This page prints "Hello World!" on the browser and some configuration settings of PHP. The directory structure of the created project looks like:
META-INF/
META-INF/MANIFEST.MF
WEB-INF/
WEB-INF/classes/
WEB-INF/sun-web.xml
WEB-INF/web.xml
index.jsp
index.php
Notice, "
index.jsp
" is only a template file to get started with JSPs and "sun-web.xml
" is GlassFish-specific deployment descriptor. These files are not required for this PHP application although it does not hurt to leave them in the webapp as well.
Deploy Project
". Your first PHP application in GlassFish is now deployed at "http://localhost:8080/hellophp/index.php
".Now that you have verified that your GlassFish is ready to host PHP applications, try the different applications that are described in Ludo’s blog.
Technorati: php glassfish caucho quercus
This TOTD describes how to convert a stateless session EJB to a Web service and uses information from this thread.
@javax.jws.WebService
annotation at the top of your EJB class. The modified code looks like:
@javax.ejb.Stateless
@javax.jws.WebService
public class HelloSessionBean implements server.HelloSessionLocal {
public String sayHello(String name) {
return "Hello " + name + " from session bean";
}
}
The new annotation is shown in this color.
That’s it!
There is no need to specify any additional deployment descriptor or parameters.The WSDL exposed by the EJB Web service endpoint is available at "http://localhost:8080/HelloSessionBeanService/HelloSessionBean?wsdl
". The generated WSDL looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.2-hudson-182-RC1. -->
<!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.2-hudson-182-RC1. -->
<definitions
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://server/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://server/"
name="HelloSessionBeanService">
<wsp:UsingPolicy></wsp:UsingPolicy>
<wsp:Policy wsu:Id="HelloSessionBeanPortBinding_sayHello_WSAT_Policy">
<wsp:ExactlyOne>
<wsp:All>
<ns1:ATAlwaysCapability xmlns:ns1="http://schemas.xmlsoap.org/ws/2004/10/wsat" wsp:Optional="false"></ns1:ATAlwaysCapability>
<ns2:ATAssertion xmlns:ns3="http://schemas.xmlsoap.org/ws/2002/12/policy"
xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/10/wsat" ns3:Optional="true"
wsp:Optional="true"></ns2:ATAssertion>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<types>
<xsd:schema>
<xsd:import namespace="http://server/" schemaLocation="http://localhost:8080/HelloSessionBeanService/HelloSessionBean?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"></part>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"></part>
</message>
<portType name="HelloSessionBean">
<operation name="sayHello">
<input message="tns:sayHello"></input>
<output message="tns:sayHelloResponse"></output>
</operation>
</portType>
<binding name="HelloSessionBeanPortBinding" type="tns:HelloSessionBean">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
<operation name="sayHello">
<wsp:PolicyReference URI="#HelloSessionBeanPortBinding_sayHello_WSAT_Policy"></wsp:PolicyReference>
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
</binding>
<service name="HelloSessionBeanService">
<port name="HelloSessionBeanPort" binding="tns:HelloSessionBeanPortBinding">
<soap:address location="http://localhost:8080/HelloSessionBeanService/HelloSessionBean"></soap:address>
</port>
</service>
</definitions>
Few points to notice:
A reasonable set of defaults are chosen for portType/@name
, binding/@name
, service/@name
and even the soap:address/@location
. Most of these values can be changed by specifying a different value in the @WebService
annotation.
Accordingly to EJB 3.0 specification, if @TransactionAttribute
is not specified on the method then a default value of REQUIRED
is applied. This default value is automatically converted to ATAlwaysCapability
and ATAssertion
policy assertions.
Accordingly to Web Services for Java EE, Version 1.2, webservices.xml
is optional so there is no need to write any other deployment descriptor.
Be careful not to deploy a WAR file with the context root generated (HelloSessionBeanService
) for the Web service endpoint. The EJB Web service endpoint will be inaccessible after that.
Please leave suggestions on other TOTD that you’d like to see. A complete archive is available here.
Technorati: totd webservices ejb glassfish
Watch a 25-minute video as Ed Ort deep dives on Project Tango (part of Metro) with me.
How to play the interview ? – Clicking on the image above takes you to the main page where different interviews are located. On that page, click on the Play button (sideways triangle) in the bottom left corner instead of "LOW BAND" or "HIGH BAND" buttons. More than one person asked me this question so it does seem slightly non-intuitive to me. Even I was confused but then figured out after playing around.
You can read more about Project Tango in this detailed article.
Technorati: webservices glassfish metro netbeans interview
The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress