Slow spring component scan - java

i found some posts dealing with this topic, but our situation is a bit different, so I post it here, hoping someone can help us with it.
The situation is:
We develop a rich client that is started via webstart (loaded from a server). In the client we use spring (3.0.5) for dependency injection, nothing else so far.
Since we had big trouble with slow component scans because of AOP in spring, we do not use all spring jars but the following:
spring-asm-3.0.5.RELEASE.jar
spring-beans-3.0.5.RELEASE.jar
spring-context-3.0.5.RELEASE.jar
spring-context-support-3.0.5.RELEASE.jar
spring-core-3.0.5.RELEASE.jar
spring-expression-3.0.5.RELEASE.jar
The effect we have is strange:
If we start the rich client via webstart it is quite fast (component scan in a few seconds).
Now (for some reason) i try to start our client as regular application by just having all jars on my computer and starting the app with a huge classpath.
In this scenario it takes 3-5 minutes (depending on the computer) to boot the app.
In the log i can see its the spring component scan that takes so long.
Of course the used jar files are 100% identical in both solutions.
So my fundamental question is: Where is the difference here?
I would have expected it all the way round. Long time in Webstart and fast as application.
Does anyone have a hint what could cause those long startup times in the application scenario?

Related

how to expose start/stop/status features for all java batchs running in a Web Server

My straight question is: let's say I have 10 wars deployed to my server. Inside of each one there is a simple job either coded with Spring Batch or JSR352 implementations. Then I want to start, check the status and stop them manually? What from an enterprise server would provide me that ability? For instance, let's say I have 10 batchs deployed to the same server (I use Websphere 8.5.5 ND with JDK 7 but you can have anyone in your mind). Five batchs are JSR-352 and others five are Spring Batch. I want to provide a single page for final user where he/she can start the server, see if it is running and then stop it while it is running (It is beyond this question talk about the front end side. It can be as simple a butom for start, another for stop and just refresh the page to see the current status). The question is focused in how to expose start/stop/status ability about Batchs deployed to a Web Server.
Let me explain a bit deeper. I have worked for the last 6 months in order to create few jobs with Spring Batch. For some reason, I can't start it straigh from unix shell or JCL in my company. In pratical terms it means I can't use a script starting it with command lines. I must use inside of our Websphere 8.5.5 ND. There is an amazing application named Spring Batch Admin that would fit my necessity but, to make short, I can't use it here.
It is beyond this question compare Spring Batch with JSR 352. For my question I really don't care which one I will use as long as I can offer someway for a monitor/operator/user to see in a web page someway to start/stop/check status. So if you can answer only for JSR 352 or only for Spring Batch it will be perfect. Obviously a bit better if there is some generic way to cover both.
I guess, not sure, that there might be someway to use JMX or JConsole feature to do something similar to what Spring Batch Admin does but I don't have the north and it is hard for me to start without a scratch direction. I am sure it is perfectly possible otherwise it wouldn't exist an application named Spring Batch Admin offering that (I have used it very well but I can't make it works in production for local reasons).
I think in JMX because I understand JMX can register beans and expose it and I think in JConsole from the Java used for my server because it shows what is going on with the same JVM used for that server.
Readers that got interested in this question but didn't understand what I mean by JSR 352 or Spring Batch Admin may get interested in this two links:
JSR352 in Websphere ND
http://www-01.ibm.com/support/docview.wss?uid=tss1wp102544&aid=1
Spring Batch Admin
https://examples.javacodegeeks.com/enterprise-java/spring/spring-batch-admin-tutorial/
Very interested movie convering both implementations:
https://www.youtube.com/watch?v=yKs4yPs-5yU
I would like to put in spot light that answer that try to compare Spring Batch with JSR352 I will downgrade the answer. It is very far away from my question and motivation.

Processing time for a request using Jolokia

I'm developping a Web Service, using Glassfish 4. When someone makes a call, I know how many time each method took. I'm saving this information on log(Log4J).
Now I want to monitorize the application using JMX (Currently I'm using Jolokia).
From what I know, there are 2 possibilities:
Implement Mbean interface and extends it on all my classes
Disadvantages: too much code and possible wasting memory and processing time)
Use JMXlogger (the information about this solution is very old)
Is there another strategy?

Timings with Spring application contexts

I'm currently trying to track down a performance issue and I've found a large amount of time is being spent in the code where you request a bean from a ApplicationContext:
ApplicationContext.getBean(String beanName);
Do you know if it's possible to turn on any debug or log information within Spring so that I can see all the objects that are instantiated from this call as well as the times to create them?
I've been trying to profile with Yourkit, but the operation only take 1.4 seconds in total and only on the first call, so Yourkit seems to struggle with short lived, one off calls like this.
It's why I was heading down the logging route.
Spring uses log4j, so you can set your log level to debug and see what you get. It'll be a lot of output. I'd advice not logging it to the console - write it to a file.
How did draw that conclusion? Are you profiling your app with Visual VM, with all the plugins installed?
I'd bet that the app context is not the issue. If the time spent in the app context is large, it should just be on startup when Spring is reading and parsing the configuration, instantiating and wiring beans. Once it's done the cost is amortized over the life of your app. For most web apps this is a startup cost, not a reflection on the experience users have when using your site.
It's far more likely to be in your code. Be sure that you aren't being mislead by not taking a comprehensive view.

NBP rich client in a multi-tier enterprise application?

Just started a project that involves a rich client implemented in Netbeans Platform (NBP), Spring framework is chosen to implement business logic and for data access. Since I've come from a web application development background, I have some questions and would also like some suggestions.
What are the options for a rich client to integrate with Spring?
Any best practices/books/docs regarding a rich client in a multi-tier Java EE environment?
Anything that needs special attention?
We recently went through a similar experience at the company I work for. Sadly, we couldn't find any sort of definitive guide for the process. What we found were partial guides here and there. I'm not certain how others have dealt with this issue, and I am eager to see if any other solutions are posted here. I can, however, tell you how we handled it and hope that you can learn from our experience.
From the onset, we knew that we wanted to be able to control what version of Spring (and, in our case, Hibernate) we would use. Naturally, the versions built into the NetBeans IDE are a bit dated and we wanted to have the cutting-edge available when developing our server code.
What we ended up doing was creating two separate projects: one for our server code (our Services, DAOs, and Domain entities) and one for our client application. We then jared up the server code, copied the jar and its dependencies to the client project, and listed those jars as dependencies in the client code. We created a module in our NetBeans project called SpringHibernate, which housed those jars, and which almost every other module depended on.
I would recommend creating an ant task that will strip out the version numbers of your jars before adding them to your NetBeans project. This allows you to seamlessly update your jars in the server code without the client code ever knowing the difference. (NetBeans can be kind of picky when you start removing and re-adding jars.)
The first major task then is to create a Util class that can load your applicationContext.xml and return beans from the context. That process is outlined here.
One of the major snags that we hit was the creation of Sessions (or EntityManagers in JPA terms). The NetBeans Platform is a highly threaded environment, and EntityManagers are designed to only work on a single thread. To get around this we went with the Open Session In View route*. We created a class that could load the same EntityManager into any thread that requested it. We then created client proxies of our services which would load the EntityManager into its thread before calling the actual Spring-managed service. The added bonus of creating client proxy services was that they were able to be found with Lookup.getDefault().lookup(Service.class) via the #ServiceProvider annotation.
You then should create a custom LifeCycleManager that can teardown and close your EntityManager and EntityManagerFactory on application shutdown.
I hope this helps!
*I know that Open Session in View has been labeled as an AntiPattern, but as long as you understand the problems associated with it you can mitigate those issues (by caching things objects that are unlikely to change over time, making smart database calls, etc.). Plus, I remember during our research we found a forum post by Gavin King stating that Open Session In View is the recommended route for client applications. Of course, I can't find the post now, but it's out there somewhere.

What's the best way to share business object instances between Java web apps using JBoss and Spring?

We currently have a web application loading a Spring application context which instantiates a stack of business objects, DAO objects and Hibernate. We would like to share this stack with another web application, to avoid having multiple instances of the same objects.
We have looked into several approaches; exposing the objects using JMX or JNDI, or using EJB3.
The different approaches all have their issues, and we are looking for a lightweight method.
Any suggestions on how to solve this?
Edit: I have received comments requesting me to elaborate a bit, so here goes:
The main problem we want to solve is that we want to have only one instance of Hibernate. This is due to problems with invalidation of Hibernate's 2nd level cache when running several client applications working with the same datasource. Also, the business/DAO/Hibernate stack is growing rather large, so not duplicating it just makes more sense.
First, we tried to look at how the business layer alone could be exposed to other web apps, and Spring offers JMX wrapping at the price of a tiny amount of XML. However, we were unable to bind the JMX entities to the JNDI tree, so we couldn't lookup the objects from the web apps.
Then we tried binding the business layer directly to JNDI. Although Spring didn't offer any method for this, using JNDITemplate to bind them was also trivial. But this led to several new problems: 1) Security manager denies access to RMI classloader, so the client failed once we tried to invoke methods on the JNDI resource. 2) Once the security issues were resolved, JBoss threw IllegalArgumentException: object is not an instance of declaring class. A bit of reading reveals that we need stub implementations for the JNDI resources, but this seems like a lot of hassle (perhaps Spring can help us?)
We haven't looked too much into EJB yet, but after the first two tries I'm wondering if what we're trying to achieve is at all possible.
To sum up what we're trying to achieve: One JBoss instance, several web apps utilizing one stack of business objects on top of DAO layer and Hibernate.
Best regards,
Nils
Are the web applications deployed on the same server?
I can't speak for Spring, but it is straightforward to move your business logic in to the EJB tier using Session Beans.
The application organization is straight forward. The Logic goes in to Session Beans, and these Session Beans are bundled within a single jar as an Java EE artifact with a ejb-jar.xml file (in EJB3, this will likely be practically empty).
Then bundle you Entity classes in to a seperate jar file.
Next, you will build each web app in to their own WAR file.
Finally, all of the jars and the wars are bundled in to a Java EE EAR, with the associated application.xml file (again, this will likely be quite minimal, simply enumerating the jars in the EAR).
This EAR is deployed wholesale to the app server.
Each WAR is effectively independent -- their own sessions, there own context paths, etc. But they share the common EJB back end, so you have only a single 2nd level cache.
You also use local references and calling semantic to talk to the EJBs since they're in the same server. No need for remote calls here.
I think this solves quite well the issue you're having, and its is quite straightforward in Java EE 5 with EJB 3.
Also, you can still use Spring for much of your work, as I understand, but I'm not a Spring person so I can not speak to the details.
What about spring parentContext?
Check out this article:
http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html
Terracotta might be a good fit here (disclosure: I am a developer for Terracotta). Terracotta transparently clusters Java objects at the JVM level, and integrates with both Spring and Hibernate. It is free and open source.
As you said, the problem of more than one client web app using an L2 cache is keeping those caches in synch. With Terracotta you can cluster a single Hibernate L2 cache. Each client node works with it's copy of that clustered cache, and Terracotta keeps it in synch. This link explains more.
As for your business objects, you can use Terracotta's Spring integration to cluster your beans - each web app can share clustered bean instances, and Terracotta keeps the clustered state in synch transparently.
Actually, if you want a lightweight solution and don't need transactions or clustering just use Spring support for RMI. It allows to expose Spring beans remotely using simple annotations in the latest versions. See http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.
You should take a look at the Terracotta Reference Web Application - Examinator. It has most of the components you are looking for - it's got Hibernate, JPA, and Spring with a MySQL backend.
It's been pre-tuned to scale up to 16 nodes, 20k concurrent users.
Check it out here: http://reference.terracotta.org/examinator
Thank you for your answers so far. We're still not quite there, but we have tried a few things now and see things more clearly. Here's a short update:
The solution which appears to be the most viable is EJB. However, this will require some amount of changes in our code, so we're not going to fully implement that solution right now. I'm almost surprised that we haven't been able to find some Spring feature to help us out here.
We have also tried the JNDI route, which ends with the need for stubs for all shared interfaces. This feels like a lot of hassle, considering that everything is on the same server anyway.
Yesterday, we had a small break through with JMX. Although JMX is definately not meant for this kind of use, we have proven that it can be done - with no code changes and a minimal amount of XML (a big Thank You to Spring for MBeanExporter and MBeanProxyFactoryBean). The major drawbacks to this method are performance and the fact that our domain classes must be shared through JBoss' server/lib folder. I.e., we have to remove some dependencies from our WARs and move them to server/lib, else we get ClassCastException when the business layer returns objects from our own domain model. I fully understand why this happens, but it is not ideal for what we're trying to achieve.
I thought it was time for a little update, because what appears to be the best solution will take some time to implement. I'll post our findings here once we've done that job.
Spring does have an integration point that might be of interest to you: EJB 3 injection nterceptor. This enables you to access spring beans from EJBs.
I'm not really sure what you are trying to solve; at the end of the day each jvm will either have replicated instances of the objects, or stubs representing objects existing on another (logical) server.
You could, setup a third 'business logic' server that has a remote api which your two web apps could call. The typical solution is to use EJB, but I think spring has remoting options built into its stack.
The other option is to use some form of shared cache architecture... which will synchronize object changes between the servers, but you still have two sets of instances.
Take a look at JBossCache. It allows you to easily share/replicate maps of data between mulitple JVM instances (same box or different). It is easy to use and has lots of wire level protocol options (TCP, UDP Multicast, etc.).

Categories

Resources