Friday, October 30, 2015

Hibernate session is closed!

WHAT! The session was closed? Hibernate has closed the shop? No more business?
2015-10-29 12:29:04 ERROR javax.faces.event.MethodExpressionActionListener[180]: org.hibernate.SessionException: Session is closed!
 at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:129)
 at org.hibernate.internal.SessionImpl.createCriteria(SessionImpl.java:1576)
 at org.huahsin.MyBoImpl.filterBottle(MyBoImpl.java:123)
 ...
 ...
 ...
This is so ridiculous!! May be I have overlooked on this matter. Remember, I have TransactionInterceptor being define in the following way:
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="add*">PROPAGATION_REQUIRED</prop>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>
Any method defined in the BO/DAO that doesn't start with add or get will expect to see this error. In my case as shown in the stack trace, I have filterBottle() defined in MyBoImpl. To fix this, I'm require to define additional transactionAttributes in TransactionInterceptor.

Thursday, October 29, 2015

I want the app to be flexible enough during run-time

In Eclipse IDE, the simplest way to configure class-path is to create a source folder. It is so clean and easy. But when using ANT to package a JAR, class-path is done in the following way:
<project ...>
   <target name="build">
      <jar destfile="./program.jar">
         <manifest>
            < attribute name="Main-Class" value="..."/>
            < attribute name="Class-Path" value="..."/>
         </manifest>
      </jar>
   </target>
</project>
Usually class-path is useful in referencing the library path. But I never though it can be use to reference configuration file, the file which usually in XML or properties pattern. Assuming configuration files were located at config_path, the class-path would be look like this:
<project ...>
   <target name="build">
      <jar destfile="./program.jar">
         <manifest>
            < attribute name="Main-Class" value="..."/>
            < attribute name="Class-Path" value="config_path/ lib_path/the.jar ..."/>
         </manifest>
      </jar>
   </target>
</project>
With this approach, I can have a greater flexibility to configure the application's behavior in anytime during run-time.

Sunday, October 25, 2015

There are two JNDI binding for EJB

This is so ridiculous, now only I got to realize there are two types of EJB JNDI context available when connecting the client to the server. Assuming I have the following JNDI binding ready:
   java:global/ejb1/AuthenticationImpl!org.huahsin.AuthenticationRemote
   java:app/ejb1/AuthenticationImpl!org.huahsin.AuthenticationRemote
   java:module/AuthenticationImpl!org.huahsin.AuthenticationRemote
   java:jboss/exported/ejb1/AuthenticationImpl!org.huahsin.AuthenticationRemote
   java:global/ejb1/AuthenticationImpl
   java:app/ejb1/AuthenticationImpl
   java:module/AuthenticationImpl
The first is org.jboss.naming.remote.client.InitialContextFactory, this will require additional library, jboss-client.jar to be loaded in the classpath. And also this is the most hassle free and easy to setup. The following code shows how this could be done:
   Properties props = new Properties();
   props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
   props.put(Context.PROVIDER_URL, "remote://127.0.0.1:4447");

   InitialContext context = new InitialContext(props);

   AuthenticationRemote bean = (AuthenticationRemote) context.lookup("ejb1/AuthenticationImpl!org.huahsin.AuthenticationRemote");
The second is org.jboss.ejb.client.naming, it consists of two parts. The first is the setup in the code, as shown in the following:
   Hashtable props = new Hashtable();
   props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
  
   InitialContext context = new InitialContext(props);

   String appName = "";
   String moduleName = "ejb1";
   String distinctName = "";
   String beanName = AuthenticationImpl.class.getSimpleName();
   String interfaceName = AuthenticationRemote.class.getName();
   String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + interfaceName;
  
   AuthenticationRemote bean = (AuthenticationRemote) context.lookup(name);
The second part would be the configuration file, jboss-ejb-client.properties, to be placed in the classpath. Missing this would not be able to establish connection to the server. The content of the configuration is as follows:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
 
remote.connections=default
 
remote.connection.default.host=127.0.0.1
remote.connection.default.port = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
Phew! Finally, I got the things clear.

Thursday, October 22, 2015

org.jboss.naming.remote.client.InitialContextFactory was not found in JBoss server runtime

The same piece of code, execute on different PCs, I'll have different results.
 Properties props = new Properties();
 props.put("java.naming.factory.url.pkgs", "org.jboss.ejb.client.naming");
 props.put("java.naming.factory.initial", "org.jboss.naming.remote.client.InitialContextFactory");
 props.put("java.naming.provider.url", "remote://127.0.0.1:4447");
 props.put("jboss.naming.client.ejb.context", "true");
 props.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT","false");

 InitialContext context = new InitialContext(props);

The above code was compiled and execute successfully without error. But when I move the piece to another PC, the compilation will fail and following error would be seen.
Caused by: java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory
 at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
 at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:274)
 at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:72)
 at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:61)
 at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:671)
 ... 4 more
Although I do have already configured JBoss EAP 6 as the server runtime in my project configuration, unfortunately none of the JARs found the org.jboss.naming.remote.client.InitialContextFactory class. Actually, this class can be found in jboss-client.jar and it was so unlucky that it has been excluded being a member of Jboss server runtime. Sigh... Thus, I have to explicitly include this JAR into the classpath and it is easily found in <jboss_root>\bin\client.

Sunday, October 18, 2015

I'm so confused with WSDL

I’m confused, I’m screwed.

I’m confused because there seems so many things need to be done in order to generate a WSDL file. I need to create the POJO class; I need to create the XSD; I need to build the WSDL and link XSD together; I need to create publisher class to publish the web service. And then generate the JAX-WS JAVA artifacts… No, I don’t need that at the moment. Let’s see how I begin this mess.

With bottom up approach, one way to construct the JAX-WS Java artifacts is through the Endpoint class. Like what I did with the following code:
@WebService(serviceName="HelloWorldService", portName="HelloWorldPort", endpointInterface="org.huahsin.ws.HelloWorld")
public class HelloWorldEndpoint {
 public static void main(String args[]) {
  HelloWorld inst = new HelloWorld();
  Endpoint.publish("http://localhost:8080/wsAsync", inst);
  System.out.println("service published");
 }
}
Assuming I have the HelloWorld POJO declared in this way:
@WebService(serviceName="HelloWorldService")
public class HelloWorld {
 @WebMethod(operationName="hello")
 public String hello(@WebParam(name="name") String name) {
  return "Hello " + name;
 }
}
Executes the program, send the URL (http://localhost:8080/wsAsync?wsdl) to the web browser, then the WSDL content will be shown. After that save the WSDL content, by selecting all the text in the web page, and paste it into notepad, then save it as a file with WSDL file extension. Anyhow, this isn’t a good approach to generate the WSDL file.

Actually, there is a better approach for doing it with wsgen command. The usage is as shown below:

C:\project\ws>wsgen -verbose -wsdl -keep -cp target\classes org.huahsin.HelloWorld

Don’t confuse with –cp option, it is referring to the path where the compiled class of org.huahsin.HelloWorld is stored (I thought it was the JDK path). And the –wsdl option is to tell the wsgen command to generate a WSDL file. I feel much better with the tool now. Besides that, JBoss does have the similar utility, named wsprovide, and the usage is as follow:

C:\project\ws>wsprovide -w -k -c target\classes org.huahsin.HelloWorld

But make sure the \bin is registered in environment variable before it is usable.

Thursday, October 1, 2015

wsimport wasn't covered by lifecycle configuration

I was working on a project that requires me to use Maven to generate Java artifacts from WSDL. For the first time, I'm doing it with Maven. Somehow the Eclipse m2e seem doesn’t support wsimport lifecycle, my Maven configuration is as follows:
<plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>jaxws-maven-plugin</artifactId>
   <executions>
      <execution>
            <goals>
               <goal>wsimport</goal>
            </goals>
            <configuration>
               <wsdlLocation>http://huahsin.org/wsasync</wsdlLocation>
               <wsdlDirectory>${basedir}/resources</wsdlDirectory>
               <keep>true</keep>
               <packageName>org.huahsin.ws</packageName>
               <sourceDestDir>${basedir}/src</sourceDestDir>    
            </configuration>
         </execution>
      </executions>
</plugin>
This is the original error message:
  Plugin execution not covered by lifecycle configuration: 
  org.codehaus.mojo:jaxws-maven-plugin:1.12:wsimport (execution: default, phase: generate-sources)
I though by adding the generate-sources phase into the configuration will help. But in fact, it wouldn’t.
   …
 
   <executions>
      <execution>
         <phase>generate-sources</phase>
            <goals>
   … 
Sigh~ asking myself why do I still want to scratch my head on a problem since m2e has already provided me the solution? With the POM file open in Eclipse, hover to that error, click on the Discover new m2e connectors to retrieve the jaxws-maven-plugin connector. This connector is specially designed to handle wsimport for me. Make me worry free.