Showing posts with label EJB. Show all posts
Showing posts with label EJB. Show all posts

Sunday, December 07, 2014

WildFly 8.2.0.Final release - Quick overview of the changes

It's been a while since I last wrote on this blog. Although I have had some topics that I wanted to blog about, I just haven't found enough time to do it. I finally decided to write this up today after I saw a mail from one of the JBoss community members, checking up on why there haven't been any updates here lately (thanks for checking, Bhaskar! :)).

Before I move on to some technical things, a quick personal update - It's now been more than a year now since I changed jobs. I no longer work at Red Hat, JBoss. My (almost) 5 years at JBoss have been very fruitful and I enjoyed being part of the (JBoss AS/WildFly) application server development team. Last year, I decided to move on to something different and the right opportunity came along and I decided to take it up. Some of you know that I've been involved with the JBoss community for longer than the 5 years that I had been employed at Red Hat. I have been a JBoss community member since around 2004/2005, so even though I have moved on from Red Hat, I am still active in the JBoss forums.

Now that you all know what I've been upto, let's move on to some technical things.

WildFly 8.2.0.Final released!


The WildFly team just released the 8.2.0.Final version of WildFly some days back. As usual, it's available for download on the project's download page http://wildfly.org/downloads/. This is mainly a bug fix (plus some features) release in the 8.x series. I for one, was pleased to see this release happen because it allows the community to receive bug fixes on top of 8.1.0.Final release, which has been tested/used in the community for quite some time now. The WildFly team has indicated that this will be the last release in the 8.x series which sounds reasonable, given that the development team has already moved on to work on the 9.x series. It's never easy to work/maintain more than one major version of the code, especially in the context of bug fixes and backward compatibility.

What does WildFly 8.2.0.Final contain?


The complete overview of changes in available in this announcement on Jason's blog http://wildfly.org/news/2014/11/20/WildFly82-Final-Released/. CDI spec upgrade and improved WebSocket support are the main items in terms of feature set. There's also this note in the release notes:
- EJBs in WARs now inherit the WAR security domain

There was a recent forum thread, where one of the users asked what that really means. Here's some background to that change https://issues.jboss.org/browse/WFLY-3102. As noted in that JIRA, this was feature request that was raised in the context of EJBs packaged in .war deployments. Most of you, I guess, will be aware that Java EE spec allows EJBs to be deployed as part of the .war deployment. What this means is that you can place your EJB classes within the .war/WEB-INF/classes or within a jar in .war/WEB-INF/lib. Although, this sounds straightforward for the end users, there are some technical implications to this (given the way Java EE "components" and "modules" are defined and configured within the server ecosystem). One such detail, is the way one configures the EJBs that are part of the .war deployment. Remember that if this EJB was part of a separate EJB module (within a .jar packaging outside of the .war) then one would use the ejb-jar.xml (and the WildFly specific jboss-ejb3.xml) as the deployment descriptors to configure it. This applies to EJBs deployed in a .war deployment too. i.e. one can use those same files for configuring EJBs. Now since these EJBs are part of a .war, the .war itself can/will have a deployment descriptor if its own (the web.xml and jboss-web.xml).

With that context, consider a case where the you have EJBs within the .war deployment and your .war deployment descriptor (the jboss-web.xml) configures a specific security domain for that deployment. Now remember that the EJBs too can configure a security domain (in jboss-ejb3.xml) and if none is configured and security is enabled on some EJBs, then the default "other" security domain gets used. So let's say your .war deployment, in which the EJBs reside, states that it wants to use "foo-bar" security domain and the EJBs, within that deployment, don't specify any specific security domain. So what should one expect in such scenario? Should the EJBs use the security domain configured at the .war level or should they default to the "other" security domain (since the EJB deployment descriptors don't specify any specific security domain configuration). The previous versions of WildFly had decided to use the default "other" security domain for the EJBs in such a case. Of course, the EJBs could use a jboss-ejb3.xml to set a different security domain, one which matches the jboss-web.xml. So that JIRA which I linked to earlier requested for a better, smarter and a more logical default in such cases. So starting this 8.2.0.Final version of WildFly, if you have a .war containing the EJBs and the EJBs don't define a security domain, then the security domain for any secured EJBs in that deployment *defaults* to the one that's defined at the .war deployment level. If the .war deployment doesn't set any specific security domain, then it ultimately, defaults to the "other" security domain. A good and logical change IMO. This will reduce some of the "surprises" that users have reported with previous version of WildFly, when it came to the security domain usage of EJBs in .war deployments.

For more about this, you can read the discussion here https://developer.jboss.org/thread/250375 and ask any questions you have around this, in that thread.

What are the other notable things in WildFly 8.2.0.Final?


Although, not specific to 8.2.0.Final, the WildFly release contain a "patch" distribution which you can use if you already are using WildFly 8.1.0.Final and just want to "upgrade" to this new release. WildFly 8 has patch management built in and one can apply this patch on top of an existing 8.1.0.Final version.

What's next for WildFly?


As noted earlier, the WildFly development team has moved on to the next version of the project. Work is now continuing on 9.x version which already has a Alpha version released. So going forward, from what I have read, the releases will happen in the 9.x series.


Tuesday, March 26, 2013

Java EE 7 and EJB 3.2 support in JBoss AS 8

 Update (June 10 2013): JBoss AS is now known as WildFly. This post was written before WildFly 8.0.0.Alpha1 was released. Any references to JBoss AS8 in this article should be considered as a reference to WildFly 8. Read my next article here http://jaitechwriteups.blogspot.in/2013/06/wildfly-release-and-history-behind-the-release.html which explains what WildFly is and why JBoss AS was renamed to WildFly.


Some of you might be aware that the Public Final Draft version of Java EE 7 spec has been released. Among various other new things, this version of Java EE, brings in EJB 3.2 version of the EJB specification. EJB 3.2 has some new features compared to the EJB 3.1 spec. I'm quoting here the text present in the EJB 3.2 spec summarizing what's new:

The Enterprise JavaBeans 3.2 architecture extends Enterprise JavaBeans to include the following new functionality and simplifications to the earlier EJB APIs:
  • Support for the following features has been made optional in this release and their description is moved to a separate EJB Optional Features document:
    • EJB 2.1 and earlier Entity Bean Component Contract for Container-Managed Persistence
    • EJB 2.1 and earlier Entity Bean Component Contract for Bean-Managed Persistence
    • Client View of an EJB 2.1 and earlier Entity Bean
    • EJB QL: Query Language for Container-Managed Persistence Query Methods
    • JAX-RPC Based Web Service Endpoints
    • JAX-RPC Web Service Client View

  • Added support for local asynchronous session bean invocations and non-persistent EJB Timer Service to EJB 3.2 Lite.

  • Removed restriction on obtaining the current class loader; replaced ‘must not’ with ‘should exercise caution’ when using the Java I/O package.

  • Added an option for the lifecycle callback interceptor methods of stateful session beans to be executed in a transaction context determined by the lifecycle callback method's transaction attribute.

  • Added an option to disable passivation of stateful session beans.

  • Extended the TimerService API to query all active timers in the same EJB module.

  • Removed restrictions on javax.ejb.Timer and javax.ejb.TimerHandle references to be used only inside a bean.

  • Relaxed default rules for designating implemented interfaces for a session bean as local or as remote business interfaces.

  • Enhanced the list of standard activation properties.

  • Enhanced embeddable EJBContainer by implementing AutoClosable interface.



As can be seen, some of the changes proposed are minor. But there are some which are useful major changes. We'll have a look at a couple of such changes in this article.

1) New API TimerService.getAllTimers()


EJB 3.2 version introduces a new method on the javax.ejb.TimerService interface, named getAllTimers. Previously the TimerService interface had (and still has) a getTimers method. The getTimers method was expected to return the active timers that are applicable for the bean on whose TimerService, the method had been invoked (remember: there's one TimerService per EJB).

In this new EJB 3.2 version, the newly added getAllTimers() method is expected to return all the active timers that are applicable to *all beans within the same EJB module*. Typically, an EJB module corresponds to a EJB jar, but it could also be a .war deployment if the EJBs are packaged within the .war. This new getAllTimers() method is a convenience API for user applications which need to find all the active timers within the EJB module to which that bean belongs.

2) Ability to disable passivation of stateful beans


Those familiar with EJBs will know that the EJB container provides passivation (storing the state of the stateful bean to some secondary store) and activation (loading the saved state of the stateful bean) capability to stateful beans. However, previous EJB versions didn't have a portable way of disabling passivation of stateful beans, if the user application desired to do that. The new EJB 3.2 version introduces a way where the user application can decide whether the stateful bean can be passivated or not.

By default, the stateful bean is considered to be "passivation capable" (like older versions of EJB). However, if the user wants to disable passivation support for certain stateful bean, then the user has the option to either disable it via annotation or via the ejb-jar.xml deployment descriptor.

Doing it the annotation way is as simple as setting the passivationCapable attribute on the @javax.ejb.Stateful annotation to false. Something like:

 @javax.ejb.Stateful(passivationCapable=false) // the passivationCapable attribute takes a boolean value  
 public class MyStatefulBean {  
 ....  
 }  

Doing it in the ejb-jar.xml is as follows:


 <?xml version="1.0" encoding="UTF-8"?>  
 <ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee  
      http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd"  
      version="3.2">  
   <enterprise-beans>  
     <session>  
       <ejb-name>foo-bar-bean</ejb-name>  
       <ejb-class>org.myapp.FooBarStatefulBean</ejb-class>  
       <session-type>Stateful</session-type>  
       <!-- passivation-capable element takes either a true or a false value -->  
       <passivation-capable>false</passivation-capable>  
     </session>  
     ...  
   </enterprise-beans>  
 </ejb-jar>  


Two important things to note in that ejb-jar.xml are the version=3.2 attribute (along with the http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd schema location) on the ejb-jar root element and the passivation-capable element under the session element.

So, using either of these approaches will allow you to disable passivation on stateful beans, if you want to do so.

Java EE 7 and EJB 3.2 support in JBoss AS8:


JBoss AS8 has been adding support for Java EE 7 since the Public Final Draft version of the spec has been announced. Support for EJB 3.2 is already added and made available. Some other Java EE 7 changes have also made it to the latest JBoss AS 8 builds. To keep track of the Java EE 7 changes in JBoss AS8, keep an eye on this JIRA https://issues.jboss.org/browse/AS7-6553.

To use the already implemented features of Java EE 7 in general or EJB 3.2 in particular, you can download the latest nightly build/binary of JBoss AS from here. Give it a try and let us know how it goes. For any feedback, questions or if you run into any kind of issues, feel free to open a discussion thread in our user forum here.



Wednesday, January 20, 2010

EJB3.1 initial support in JBoss AS

Good news for those waiting for EJB3.1 support in JBoss AS :) The upcoming JBoss AS 6.0.0.M2 will have the initial EJB3.1 support. The AS release is scheduled a few weeks from now. Last weekend we added some of the EJB3.1 support to the JBoss AS trunk. This includes the no-interface view for EJBs and also deployment of EJBs through .war files. So in it's present state, the AS trunk has these EJB3.1 features available.

Those of you who want to try this out and provide feedback/bug reports etc... please follow this thread in the EJB3 user forum. Good luck and let us know, in the forums, how it goes!

Tuesday, April 07, 2009

JBoss EJB3 tutorials and docs

I thought i will blog this, since i have been seeing many of the community members looking for some documentation or tutorials for EJB3 on JBoss. Obviously, for anyone who's trying to learn a new technology, the best place to start will be the tutorials. Many of you might be already aware that the new JBossAS-5.x series have been released to the community. Just recently we uploaded a completely new set of EJB3 tutorials and reference documentation targeted for JBossAS-5. These tutorials and reference documentation is available here. The earlier set of tutorials which are targeted for AS-4.x are available here.

The new set of tutorials have been modified to work against AS5. The changes mainly include changes to deployment descriptors or any JBoss specific EJB3 features. The complete source code for the tutorials is available for download at the same URL.

The important point to note is that these tutorials will be maintained to work against the latest release of EJB3 plugin. So what is EJB3 plugin? JBossAS-5 ships with EJB3 support by default. As you all know, the JBoss EJB3 project and the JBoss AS project are maintained separately and as such have their own release cycles. So what happens if we introduced something new in EJB3 or do a major bug fix for the community in EJB3 project? How do we make it available to the community who use EJB3 support provided by AS5? That's where the EJB3 plugin comes in picture. The EJB3 plugin provides a mechanism where you can patch newer versions of EJB3 into AS5. This way, if there are any major bug fixes or enhancements you are waiting for from the EJB3 community, then you can use the EJB3 plugin to patch it in AS5.

The next question would be, when and where do i get the EJB3 plugin for the AS. EJB3 project has come up with a release cycle where, every 2nd and 4th Friday of the month there will be a EJB3 release. These releases are downloadable at the JBoss EJB3 download page . So how do you use this plugin against the AS? It's pretty simple. All you need is:

- JBossAS-5 installation
- Ant 1.7

Download the plugin which is nothing but a jar file and run the following command


java -jar jboss-ejb3-plugin-x.x.x-installer.jar < path to JBossAS5.x >


Note that jboss-ejb3-plugin-x.x.x-installer.jar is the name of the jar file you downloaded.

So that gives you an idea about what the plugin is. Coming back to the EJB3 tutorials, I mentioned earlier that these tutorials are maintained to work against the latest release of EJB3 plugin. What this means is, you won't find a tutorial in a broken state (tutorials that are no longer running). The tutorials are tested against every release of the EJB3 plugin. So if something in the tutorials breaks, then that's fixed at the right place before they are released to the community.

If anyone has any suggestions or questions about the tutorials or the EJB3 docs, feel free to start a discussion in the JBoss EJB3 forum

Thursday, August 24, 2006

Lookup an EJB from a different application, deployed on the same server, in JBoss


Question:
I have a web application through which i want to access an EJB which is deployed as a separate appliaction on the same server. How do i do it?
Answer:
In the web.xml of your war(the web application through which you want to access the EJB), have the following entry:


<ejb-ref>

<ejb-ref-name>GiveAnNameByWhichYouWouldLikeToReferTheBeanInYourWebApp</ejb-ref-name>
<ejb-ref-type>session</ejb-ref-type>
<home>packageName.ClassNameOfTheHomeObjectOfTheBeanYouWantToRefer</home>
<remote>packageName.ClassNameOfTheRemoteObjectOfTheBeanYouWantToRefer</remote>
</ejb-ref>


In the jboss-web.xml of your war, have the following entry:


<ejb-ref>
<!--The ejb-ref-name should be same as the one given in the web.xml above -->
<ejb-ref-name>GiveANameByWhichYouWouldLikeToReferTheBeanInYourWebApp</ejb-ref-name>
<!--Example:somecontext/somejndiName.YouWillFindThisJndiNameInTheJboss.xmlOfTheEJB-->
<jndi-name>TheJndiNametoWhichTheBeanIsBound</jndi-name>
</ejb-ref>


For more info, have a look at the dtds of web.xml (http://java.sun.com/dtd/web-app_2_3.dtd) and jboss-web.xml(http://www.jboss.org/j2ee/dtd)
In your code, do the lookup as:

 
Context ic = new InitialContext();
Object home=ic.lookup("java:comp/env/TheNameThatYouHadGivenInEjb-ref-nameTagOfJbossWeb.xml");


Here’s an example:

web.xml:

<ejb-ref>
<ejb-ref-name>MyTestBean</ejb-ref-name>
<ejb-ref-type>session</ejb-ref-type>
<home>com.test.ejb.MyBeanHome</home>
<remote>com.test.ejb.MyBeanRemote</remote>
</ejb-ref>



jboss-web.xml:

<ejb-ref>
<ejb-ref-name>MyTestBean</ejb-ref-name>
<jndi-name>myejb/test/MyTestBean</jndi-name>
</ejb-ref>


Lookup code:

Context ic = new InitialContext();
Object ejbHome = ic.lookup("java:comp/env/MyTestBean");

Tuesday, July 04, 2006

Accessing a secure EJB through a standalone java client

To access a secure resource(may be a EJB), from a standalone client, you need to do a JAAS login. Here's an simple example which shows how to implement the same. But before going to the example, here's the reason why we need to do a login. Consider a secured EJB "MyTestEJB", deployed on a app server. The normal proceedure that you follow in a web-application to lookup the EJB and invoke a method on the same is as follows:

Context context = new InitialContext();
//lookup the home object
Object lookupObj = context.lookup("MyTestEJBHomeJndiName");
MyTestEJBHome home = (MyTestEJBHome) PortableRemoteObject.narrow(lookupObj, MyTestEJBHome.class);
//create the bean object from the home object
MyTestEJB myBean = home.create();
//invoke the method on the bean
myBean.someMethod();


In the steps above, when the method create is called on the home object, the app server internally checks whether the user who is doing this operation, is authenticated and authorised to do the same. If not, it will throw a SecurityException. The above statements will usually work in a web-application where usually you have a login page to carry out the login process.

Now, consider the case with a standalone java client which has just got a main method and which needs to invoke the secure bean. The application server will have no knowledge about which user is trying to do the operations on the bean(is he authenticated or authorised?). This is the reason why the standalone client needs to do a JAAS login, to let the application server know which user is trying to do the operation on the bean. Now lets look at the code for doing the same. Here we have a standalone java client with a main() method:


package myapp;

import javax.ejb.CreateException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.io.Serializable;
import java.rmi.RemoteException;

/**
*
* Stand-alone client invoking a method on a secure EJB
*
*/
public final class SomeStandAloneClient {


/**
* Default constructor
*
*/
public SomeStandAloneClient() {

}

/**
* Main method
*
* @param args Command line arguments
*/
public static void main(String[] args) {

//obtain the username and password which are passed as part of command line arguments
String userName = args[0];
String password = args[1];

System.out.println("Logging in user: " + userName);

/*
* The name of the file which will contain the login configurations
*/
final String authFile = "someFilename.someExtension";

/*
* Set the filename above, as part of system property, so that while doing a login,
* this file will be used to check the login configurations
*/
System.setProperty("java.security.auth.login.config", authFile);

/*
* During the login process(i.e. when the login() method on the LoginContext is called),
* the control will be transferred to a CallbackHandler. The CallbackHandler will be
* responsible for populating the Callback object with the username and password, which
* will be later on used by the login process
*
* The "MyCallbackHandler" is your own class and you can give any name to it. MyCallbackHandler
* expects the username and password to be passed through its constructor, but this is NOT
* mandatory when you are writing your own callback handler.
*
*
*/
MyCallbackHandler handler = new MyCallbackHandler(userName,password);

try {

/*
* Create a login context. Here, as the first parameter, you will specify which
* configuration(mentioned in the "authFile" above) will be used. Here we are specifying
* "someXYZLogin" as the configuration to be used. Note: This has to match the configuration
* specified in the someFilename.someExtension authFile above.
* The login context expects a CallbackHandler as the second parameter. Here we are specifying
* the instance of MyCallbackHandler created earlier. The "handle()" method of this handler
* will be called during the login process.
*/
LoginContext lc = new LoginContext("someXYZLogin",handler);

/*
* Do the login
*/
lc.login();

System.out.println("Successfully logged in user: " + userName);


} catch (LoginException le) {

System.out.println("Login failed");
le.printStackTrace();
return;
}

try{

/*
* Now that the user has logged in, invoke the method on the EJB
*/

Context context = new InitialContext();

//lookup the home object
Object lookupObj = context.lookup("MyTestEJBHomeJndiName");
MyTestEJBHome home = (MyTestEJBHome) PortableRemoteObject.narrow(lookupObj, MyTestEJBHome.class);

//create the bean object from the home object
MyTestEJB myBean = home.create();

//invoke the method on the bean
myBean.someMethod();


} catch (RemoteException re) {

System.out.println("Remote exception: ");
re.printStackTrace();
return;

} catch (NamingException ne) {

System.out.println("NamingException: ");
ne.printStackTrace();
return;

} catch (CreateException ce) {

System.out.println("CreateException: ");
ce.printStackTrace();
return;
}


} //end of main()

} //end of SomeStandAloneClient

Now the CallbackHandler:

package myapp;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

/**
*
* CallbackHandler which will be invoked by the login module during the login
* process of the client. This is a simple CallbackHandler which sets the username
* and password, which will be later used by the Login module for authorizing the
* subject. This class only handles NameCallback and PasswordCallback. It throws
* an UnsupportedCallbackException, if the Callback is other than the two mentioned
* above.
* The username and password are provided as input to this class through its constructor.
*
*
*/
public class MyCallbackHandler implements CallbackHandler {

/**
* Username which will be set in the NameCallback, when NameCallback is handled
*/
private String username;

/**
* Password which will be set in the PasswordCallback, when PasswordCallback is handled
*/
private String password;

/**
* Constructor
* @param username The username
* @param password The password
*/
public MyCallbackHandler(String username, String password) {
this.username = username;
this.password = password;
}

/**
* @param callbacks Instances of Callbacks
* @throws IOException IOException
* @throws UnsupportedCallbackException If Callback is other than NameCallback or PasswordCallback
*/
public void handle(Callback callbacks[]) throws IOException, UnsupportedCallbackException {

for(int i = 0; i < callbacks.length; i++) {
if(callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(username);
} else if(callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(password.toCharArray());
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}

}
}
}

The file containing the login configuration(in our case "someFilename.someExtension"):

someXYZLogin{
org.jboss.security.ClientLoginModule required;
};

Remember, the someXYZLogin configuration name is the same that i provided to the constructor of the LoginContext. The contents of the above file let the LoginContext know, which class will be actually responsible for doing the login. In this case, since i am using jboss, we have specified "org.jboss.security.ClientLoginModule" as the class.

Please make sure that the login configuration file is under the same directory from where you will be running your client.

The command to run your client is the same that you would use to run a normal java class:


java SomeStandAloneClient someUsername somePassword

The someUsername and somePassword will be the arguments that you will pass to the main() method.

This is just a simple example. Internally, there are a lot of things, that go on as part of login. The following link has a great explanation about the same(JAAS related things are explained starting from the "An Introduction to JAAS" section in that article). I highly recommend, to go through it atleast once:

Article on Security