Tuesday, September 24, 2013

Energy saving with Raspberry Pi ssh server

I've noticed that after couple days of running my Raspberry Pi server (Raspberry Pi driven Dropbox alternative) I had a problem with connectivity to ssh. Not sure why, but it doesn't really bother me, as I've noticed it only once up to now. Once restarted ssh worked again.

Anyway as I don't need it to be running 24/7 but rather there are couple hours in night, when there is definitely no need to have it up.

Electronic timer switch

As I had a chance to buy electronic timer switch at "Flohmarkt" (in Riem seems to be one of the biggest ones), as it was a good deal I bought 3, where 2 seem to work (still it was worth it). After some googling I've found quite detailed manual (for I guess the British version).

Final setup

I ended up with following:
  • electronic timer switch has been programmed in the way it turns off at 01:00am and goes back on at some time in the morning (depending on weekday or weekend) and
  • cron job has been setup to switch the Raspberry Pi 5 minutes before hard unplug (in my setup are 5 mins enough):
    # m h dom mon dow command
    55 0 * * * /sbin/shutdown -h now
    
That's it. I neither need to worry about hard shutdown (and mess caused to my data) nor about manual startup my ssh server. It's been working fine for couple weeks already for me.

Wednesday, September 4, 2013

Handling file rollover with tail monitoring

The most of us probably already know the command:
tail -f <your_file_to_monitor>
it's useful for monitoring whatever has been appended to the file called <your_file_to_monitor>.

OK, nothing new here (probably). I could not live without it any more I guess, once I got used to it (as it offers me all the power of linux shell - like piping the output to other command, etc.).

The common use case for me is monitoring of the log files created by various java logging frameworks (log4j/sl4j/whatever is used).

Log file rollover problem

Maybe you've noticed that this works, but from time to time, no more messages are printed. Why that happens? You need to restart it to have it running again.

The common problem is the usage of file rollover (for example if file exceeds particular size to be backed up named by specified pattern and logging continues to the empty file named the same as the original one). This is a good practice to prevent log file unlimited growing and keeping some history across application restarts.

But the nice guys doing tail considered this option obviously. If you check the man page it has some switches that can be used for the case. Here are the relevant ones:
--retry
      keep trying to open a file even if it is inaccessible when  tail
      starts  or if it becomes inaccessible later; useful when follow-
      ing by name, i.e., with --follow=name

-f, --follow[={name|descriptor}]
      output appended data as the file grows; -f, --follow, and --fol-
      low=descriptor are equivalent

-F     same as --follow=name --retry
So to have things running even despite of log file rollover, you should go for:
tail -F <your_file_to_monitor>
That's it. Easy right?

Tuesday, September 3, 2013

EJB 3.1 - Local and Remote business interfaces must differ

Have you ever seen something like this?
Exception during lifecycle processing
java.lang.IllegalStateException: The interface XYZ cannot be both a local and a remote business interface
 at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:518)
 at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:446)
 at com.sun.enterprise.deployment.archivist.Archivist.readRestDeploymentDescriptors(Archivist.java:419)
 at com.sun.enterprise.deployment.archivist.Archivist.readDeploymentDescriptors(Archivist.java:396)
 at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:271)
 at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:280)
 at com.sun.enterprise.deployment.archivist.ApplicationArchivist.readModulesDescriptors(ApplicationArchivist.java:611)
 at com.sun.enterprise.deployment.archivist.ApplicationArchivist.openWith(ApplicationArchivist.java:229)
 at com.sun.enterprise.deployment.archivist.ApplicationFactory.openWith(ApplicationFactory.java:232)
 at org.glassfish.javaee.core.deployment.DolProvider.processDOL(DolProvider.java:188)
 at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:222)
 at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:96)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:878)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:818)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:374)
 at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
 at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:527)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:523)
 at java.security.AccessController.doPrivileged(Native Method)
 at javax.security.auth.Subject.doAs(Subject.java:356)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:522)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:546)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1423)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1500(CommandRunnerImpl.java:108)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1762)
 at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1674)
 at org.glassfish.admin.rest.resources.admin.CommandResource.executeCommand(CommandResource.java:396)
 at org.glassfish.admin.rest.resources.admin.CommandResource.execCommandSimpInMultOut(CommandResource.java:234)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
 at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:125)
 at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
 at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:91)
 at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:346)
 at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:341)
 at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)
 at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:224)
 at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
 at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
 at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
 at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
 at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
 at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
 at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:198)
 at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:946)
 at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:331)
 at org.glassfish.admin.rest.adapter.JerseyContainerCommandService$3.service(JerseyContainerCommandService.java:165)
 at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:181)
 at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:246)
 at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
 at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
 at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
 at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
 at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
 at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
 at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
 at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
 at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
 at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
 at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
 at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
 at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
 at java.lang.Thread.run(Thread.java:724)
Caused by: The interface XYZ cannot be both a local and a remote business interface
 at org.glassfish.ejb.deployment.annotation.handlers.AbstractEjbHandler.setBusinessAndHomeInterfaces(AbstractEjbHandler.java:471)
 at org.glassfish.ejb.deployment.annotation.handlers.StatelessHandler.setEjbDescriptorInfo(StatelessHandler.java:143)
 at org.glassfish.ejb.deployment.annotation.handlers.AbstractEjbHandler.processAnnotation(AbstractEjbHandler.java:270)
 at com.sun.enterprise.deployment.annotation.factory.SJSASFactory$LazyAnnotationHandler.processAnnotation(SJSASFactory.java:148)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:344)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:375)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.processAnnotations(AnnotationProcessorImpl.java:289)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:195)
 at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:134)
 at com.sun.enterprise.deployment.archivist.Archivist.processAnnotations(Archivist.java:626)
 at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:462)
 ... 69 more
where XYZ would be the name of the interface referred as Local and Remote from some stateless session bean.

Well, once I did migration to Glassfish 4.0 I've noticed that. The message is quite clear, however the question is why that would be a problem. As having one interface serving as Local as well as Remote for stateless session EJB is quite common practice I think.

Root cause

The JBoss forum message pointed me to the right direction.

The thing is that EJB 3.1 specs (implemented in Glassfish 4.0) section 4.9.7 says:
The same business interface cannot be both a local and a remote business interface of the bean.
For those interested, see the full specs on: http://download.oracle.com/otndocs/jcp/ejb-3.1-fr-eval-oth-JSpec/

Solution

OK, but how to fix it? I recommend you to read Adam Bien's suggestion.

Basically, the idea might be the analogy to package protection present in java and easy solution can be creation of extra interface that would inherit existing one and be used as Local. Possibly having Local suffix.

Monday, September 2, 2013

Is Glassfish 4.0 with Hibernate JPA a dead end?

Glassfish 4.0 with Hibernate JPA stable? Nope, see: https://java.net/jira/browse/GLASSFISH-20716

You need to go for JPA 2.1. But there is no stable release of Hibernate supporting it yet (https://hibernate.atlassian.net/browse/HHH?selectedTab=com.atlassian.jira.plugin.system.project%3aversions-panel&subset=-1)!

Well, what can I say, I was disappointed as well. Unless you do some non-production code, feel free to give it a try with 4.3.0 BetaX. Otherwise, have some rest and cross your fingers for Hibernate guys or look elsewhere.