The Sun Tech Days Boston event was held last week. As part of Sun Tech Day on Wednesday, Tom Kincaid gave a talk on Java EE 6 and the future of the EE platform. This blog captures the demonstration that we gave of an early preview of GlassFish v3 (which is implementing Java EE 6). For more information on Sun Tech Days Boston, Ryan Shoemaker has recorded his days at the conference: part 1, part 2.
In the demonstration, we wanted to show four main features of GFv3:
To put together the demonstration, I borrowed (stole) from a screencast by Jerome Dochez and a blog by Arun Gupta. Add in a daily build of NetBeans IDE and you have just the mix.
GlassFish v3: The "preview1-b2" build is available
here.
Installation is simple: just java -jar <filename>. Drop the
bin directory into your path and you're all set.
NetBeans and the GFv3 plugin: By now, the Beta 1 version of
NetBeans 6
is out. Since it hadn't been released at the time of the conference,
I went with a daily build from September 7th and grabbed the GlassFish v3
plugin from the beta update center. When you add GF to the NetBeans's server list,
NB gives you a download button to grab the app server:
JRuby: Following the directions on
Arun's blog,
you can install JRuby 1.0, add the
bin directory to your path, and install Rails with
jruby -S gem install rails -y --no-rdoc
After this, just add the JRUBY_HOME value to the end of the
asenv.* file in glassfish/config/.
Running GlassFish v3: In your glassfish/lib directory, you can see all of
the jars that make up the kernel and containers of GFv3. That little (less than 15k)
jar file called glassfish-10.0-SNAPSHOT.jar is your target. Assuming you are
in the glassfish directory, give the Java command:
java -jar lib\glassfish-10.0-SNAPSHOT.jar
...and you should see something like this:
D:\glassfish>java -jar lib\glassfish-10.0-SNAPSHOT.jar [#|2007-09-14T16:32:02.589-0400|INFO|GlassFish10.0|javax.enterprise.system.core|_ThreadID= 10;_ThreadName=Thread-2;|Listening on port 8080|#] [#|2007-09-14T16:32:02.770-0400|INFO|GlassFish10.0|javax.enterprise.system.core|_ThreadID= 10;_ThreadName=Thread-2;|Supported containers : phobos,web,php,jruby|#] [#|2007-09-14T16:32:02.790-0400|INFO|GlassFish10.0|javax.enterprise.system.core|_ThreadID= 10;_ThreadName=Thread-2;|Glassfish v3 started in 791 ms|#]Note the startup time, in this case under .8 seconds on a slightly old laptop. You can browse http://localhost:8080 to see that the server has indeed started and is serving static html content. Add another html file to
domains/domain1/docroot and you can view it in the browser, or edit
index.html
(go ahead, it's your app server!) to see changes. Now it's time to add some applications.
A web application example: In NetBeans, create a simple web application.
Ctrl-Shift-n is one way to bring up the "New Project" window, and you can
choose Web -> Web Application to create a simple web app. The
index.jsp file will come up automatically in the editor. Just add some text
of your choosing and build with F11. We called the project "jsphello" and the
war file was built in jsphello/dist/jsphello.war. If you have the GFv3 plugin,
you can deploy with NetBeans, but we deployed from the command line in order to watch
both the server and asadmin output at the same time. To deploy, use
asadmin deploy --path
<path to jsphello.war>
The asadmin script will call a Java command to deploy the application, and your
output should look something like:
D:\examples>asadmin deploy --path jsphello\dist\jsphello.war D:\examples>java -jar D:\glassfish\bin\\..\lib\admin-cli-10.0-SNAPSHOT.jar deploy --path jsphello\dist\jsphello.war SUCCESS : Application jsphello deployed successfully
Note that in the GlassFish server log, the web container is loaded when it is needed.
If you stop and restart the server now, you will that the web container is loaded at
startup since a web application has been deployed. You can undeploy the application
with:
asadmin undeploy --name jsphello
To get a list of deployed applications, use:
asadmin list-applications
After undeploying the web application and using the "list-applications" command, your
output will look like the text below. You can see that the web container is loaded,
ready for another web application to be deployed (if you restart the server, it will
not load the web container until you need it).
D:\examples>asadmin list-applications
D:\examples>java -jar D:\glassfish\bin\\..\lib\admin-cli-10.0-SNAPSHOT.jar list-applications
SUCCESS : List of deployed applications per container
ContractProvider : web_ContractProvider
properties=(Connector module=com.sun.enterprise.glassfish:gf-web-connector,
Sniffer module=class com.sun.enterprise.v3.web.WebSniffer)
A JRuby example: In NetBeans, open the New Project window and choose
Ruby -> Ruby on Rails Application. On the next page, give the application
a name (e.g., "railshello") and click Finish. After the IDE is finished generating
the files needed, you can add a controller and view for a simple "Hello World" application.
Right-click on the project name and choose Generate. Fill out the resulting dialog
as below and click Ok:
NetBeans will then generate say_controller.rb and hello.rhtml files for you. We edited the controller to add a string and then used that string in the "hello" view.
say_controller.rb:
class SayController < ApplicationController
def hello
@hello_string = "Hello World"
end
end
hello.rhtml:
<h1>Say#hello</h1> <p>Find me in app/views/say/hello.rhtml</p> <%= @hello_string %>
GlassFish v3 supports a "straight" deployment of JRuby code. To deploy our 'railshello' application, we don't have to first wrap it in a war file. We can simply call asadmin and deploy the application directory (asadmin calls the proper "java -jar ..." command):
D:\examples>asadmin deploy --path railshello D:\examples>java -jar d:\glassfish\bin\\..\lib\admin-cli-10.0-SNAPSHOT.jar deploy --path railshello SUCCESS : Application railshello deployed successfully
Watching the server log, you can see that the JRuby/Rails runtime is loaded into GFv3
as needed. Then the application is deployed and is ready to run.
To access the page once it's deployed, use http://localhost:8080/railshello/say/hello.
This directory deployment of the application makes for a very fast development
cycle. For instance, if you change the @hello_string value in say_controller.rb,
you only have to save the file and reload the page in your browser.
Adding some Java into the Ruby code: Using the same JRuby/Rails application, you
can add Java code directly into the say_controller.rb file without any other compilation
or deployment steps. For our example, we added some trivial Java code in to create a
HashMap and set the value of @hello_string using a value in this map. The
new version of say_controller.rb:
require 'java'
include_class 'java.util.HashMap'
class SayController < ApplicationController
def hello
myMap = HashMap.new
myMap.put("key", "Hello from Java code!")
@hello_string = myMap.get("key")
end
end
Now simply save the file and reload the page in your browser. The mix of Java and
JRuby code works without any other steps since we have done the directory deployment.
Finally, to undeploy the application, give the same command that you used to undeploy
the jsphello example:
asadmin undeploy --name railshello
Though this early version of GFv3 does not show anything in the log when
you undeploy the app, you can verify that it is no longer deployed with the asadmin
'list-applications' command described above.
In Java EE applications, security roles are used to restrict access to resources. A typical example is to limit access to parts of a business web site to users who are in the role "customers," while allowing users in the role "suppliers" access to other parts of the site. The application developer can specify which URLs or EJB methods can be accessed by users in which roles, and can programmatically make security decisions based on user roles at runtime. So a role is a logical privilege that can be granted to (or withheld from) users to control access within an application.
The identities of the users are stored in the application server as principals (also called "users"), which can belong to groups. Thus the privileges represented by the roles can be mapped to actual users by mapping the roles to principals or groups. This decoupling of the application's roles and the container's principals/groups allows the same application to be deployed on different servers without any changes to the code. Only the security role mapping needs to be changed in the deployment descriptor (for GlassFish, this is in sun-application.xml, sun-web.xml, or sun-ejb-jar.xml). The deployer could map the role "suppliers" (continuing above example) to an existing group "partners," a principal "admin," or even a group with the same name "suppliers." In this last case, a simplification can be made such that the default principal to role mapping is used and no role mapping is required in the deployment descriptor. This can be useful when you are writing an application and already know which groups are used in the server to which you will be deploying.
For more information on the roles and groups, please see Shing Wai's blog assign-groups in GlassFish Security realm.
The following is a simple web example that uses default principal to role mapping and so does not use a <security-role-mapping> element in the sun-web.xml file. In fact, it does not use sun-web.xml at all. To add a user and group for this example, open the admin console (normally localhost:4848) and choose: Configuration -> Security -> Realms -> file in the tree in the left pane. Then, in the right-hand pane, click Manage Users. Click New, enter "sparky" for User ID, add "users" to the Group List, and use "ee" for a password. Click OK.
This application consists of a simple jsp page, and it can only be accessed by someone in the role "users" (which matches the group "users" created above). This is the entire page, index.jsp:
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<h2>Hello ${pageContext.request.remoteUser}</h2>
</body>
</html>
This is the entire web.xml file:
<?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="h
ttp://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>myapp</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>users</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
<security-role>
<role-name>users</role-name>
</security-role>
</web-app>
To create the application, save index.jsp into a directory, create
a subdirectory "WEB-INF" and save web.xml into it, and create
the war file: 'jar cvf test.war *' The war file can also be
downloaded here.
Because security role mapping happens at deployment time, the default mapping must be turned on before the application is deployed. To turn on the default mapping, choose Configuration -> Security in the admin console. Click Enabled next to Default Principal to Role Mapping and Save.
Then the example war file can be deployed through the admin console
or with 'asadmin deploy test.war'. When you attempt to
reach the page in your browser (for instance with
http://localhost:8080/test),
you will be prompted for username and password. Entering "sparky" and
"ee" should take you to a page with Hello sparky. The example
works because the same string is used for both role and group, and
so any user in the group "users" will also be in the role "users."
The milestone 2 release of WSIT includes some "behind the scenes" changes in the way endpoint metadata can be exchanged. All WSIT endpoints can now respond to metadata exchange ("Mex") requests to obtain the wsdl and schema information. These requests are small soap messages requesting the endpoint's data. They are nothing more than an action header and an empty body, and the endpoint responds with a mex response containing wsdl and schema documents.
On the client side, wsimport can use the mex code to make requests to the service for metadata. While this is normally transparent to the user, if you're running wsimport while using a traffic monitor (such as wsmonitor) you may see these messages.
Normally, wsimport will make mex requests when you give the address of the endpoint itself such as "http://example.com/myservice." In the past, you would have to use a "?wsdl" at the end of the address to specify the WSDL location. With mex, you can still give wsimport the WSDL location, or you can use the endpoint location. In this latter case, wsimport with mex will try various mex requests: for instance, a soap 1.2 attempt followed by a soap 1.1 attempt. If these all fail, meaning that you're trying an endpoint that doesn't support mex, wsimport will default to trying the HTTP Get call to the address with "?wsdl" appended.
These mex requests and responses allow greater flexibility in how metadata is obtained, and pave the way for obtaining metadata with other transports in the future.