Currently I have a Spring project that uses Spring JPA to work with data objects and my database. All of it's functionality can be accessed by calling a single facade bean. I want to make a web application based on this data model, but I don't want to extend this project any further. Instead I would like to separate my persistence and service layers from an actual web application layer. That said, I want to package this project into a ".war" file and deploy it on my Tomcat instance. Upon demand from any other application working on Tomcat I would like to have this other application to be injected with the facade bean from my ".war".
I'm sort of new to Tomcat, and googling doesn't really help me much. So here are problems and questions that I have with this concept:
Is this the right way to do what I want? What I mean is I want behavior provided by my current Spring application to be accessible and reusable by different web applications working on one server. This might be a common case and I would like to know if this is ok as a solution.
If I have this facade bean in XML context or in annotation context of my project, how can I make this bean visible to any other application working on the same Tomcat instance upon being deployed? What should I write in my web applications to have them wired with this bean? If I want this bean to be a singleton and have all calls to it's functionality synchronized, should I do this through my code/context, or can I have Tomcat somehow take care of this for me?
Thanks in advance.
You might want to consider a REST API approach. You can't do "cross application injection" with Spring and JNDI can be cumbersome to use.
Webapps (the things that run in a servlet container like tomcat) are isolated from each other, by design. Sharing may well be a bad idea. However, to share, you can use JNDI. Setting up JNDI in tomcat 7 is described here. You will need a custom resource factory.
Related
I have a Spring Boot REST application with JPA entities and Repository classes (and related services) that works very well. Now I would like to reuse these classes for other purposes, like weekly CRON jobs and similar one-time processes which will be run from the command line.
What would be the best way to do this? The challenge is that the persistence context properties are set in application.properties, and the persistence context isn't initialized unless the Application class is initialized.
I can break out all of these classes into a separate project, and use a different way to define the persistence context there, but this becomes more of a maintenance headache if anything changes with the entities or DAO methods.
What I would really like is to have a way, from the command line, to tell Spring Boot to run another class instead of the main Application (and have the persistence context properly initialized). Any way to do this?
(Note I asked a similar question which got no response: Possible to use Spring Boot repositories from another main class?)
[Edit] is it possible to do this by creating a #component that implements the CommandLineRunner? I just want it to run a simple one-time process and not the full REST application.
There are a number of ways you could do this.
You can have multiple Main classes, and then select which application yuo want to start select main class, however if you don't know how ComponetScan works you will end up loading both applications if you are not careful.
Another way is to use Profiles, you can set the profile when you start your spring app, and then have your web profile that will start Tomcat, and a command line profile that will not .
In the project I'm working on we have choosen to have the data-layer as a completly separate module (same gradle project), which has it's own Spring Context. The data-layer spring context is then used as the parent context for other applications, as a reusable component. It is a somewhat cleaner separations of concerns, were the shared code is clearly marked, instead of having multiple applications inside the same code mudule.
I'm creating an application that relies heavily on dynamic creation/management of various resources like jms queues, webservice endpoints, jdbc connections... I have a background in java EE and am currently working on a jboss 7 server however I'm finding it increasingly difficult to control these things programmatically. The hardest thing to control seem to be the webservices. I need to be able to generate WSDLs (and XSDs) on the fly, manage the endpoints, soap handlers etc and the system simply does not seem to be set up to do that.
Other application servers don't seem to really offer any groundbreaking solutions so I'm wondering whether perhaps java EE is not the best solution to this particular problem?
Is there an application server that allows you to do just that? Is there another technology that does? Should I just roll a custom solution that integrates all the separate modules (e.g. a jms server, a web server etc...)?
UPDATE
To clarify, most java EE stuff is accomplished through a mixture of annotations and XML configuration. This however assumes that you have a POJO and/or a jar/war/... per resource.
Suppose I have a #WebServiceProvider bean which can be reused for multiple input/output combinations (for example because it dynamically redirects the content). I need to be able to deploy a new "instance" of the provider on the fly. This means I do not want to duplicate the code and redeploy it, I just want to take that one existing bean on the classpath and deploy it multiple times with different configuration settings. This also means I need to manage the WSDL dynamically. The end result should be a webservice that works pretty much like a standard webservice on the application server with the necessary integrated security, soap handlers,...
I imagine that at some point in the application server code, there must be a class "WebserviceManager" which has a method like "createWebservice(...)" that is actually used by the deployment module whenever it discovers a webservice annotation. I want access to that method and similar methods for creating jdbc connections, jms queues,...
You can use OSGi for these kind of scenarios. It is perfect for hot deployment of varios modules.
we have a frontend application that that uses Swing. We use Spring framework, but currently it is used just to autowire few beans...
What are reasonable next steps to use Spring more often?
Is it worth for non web application?
What would be advantages and disadvantages?
The advantages of using Spring (or any other dependency-injection) framework, is that you get a (hopefully) loosely coupled system, i.e you classes does not create instances of their collaborators, so you can easily change the implementation.
This is widely known as the Inversion-of-control principle (IoC, also the I in SOLID), and this is a good principle to follow. This means that spring is not limited to web applications, but can be used in any application that want to use an IoC-container (which is basically what spring-core is).
Disadvantages:
This really depends on how you look at things. There is more code (you have to define a entry-point for the injected collaborators), but that also makes the code more testable (the entry-points are seams which you can use to inject mocks and stubs in testing).
Also, you can't look at the code and immediately see which implementation of the collaborators that are used. But that also makes for good code, since you depend on interfaces, not implementations.
You get more config: either in an xml-file (old-style spring), or with annotations. Up until recently you had to rely on non-standard spring annotations to inject (#Autowired) resources, but now you can use the standard java dependency injection annotations, which means that you can switch out spring as your IoC-container without changing your code.
There are probably alot more advantages and disadvantages to using spring in your application, but this should get you started on deciding if using Dependency Inversion is a good thing for your application
More to the point of your question about Swing and Spring. In an application I have been working on we have been using spring to wire up the whole application. The different dialogs get their logic injected (no application logic should (in my opinion) be located together with gui logic). We are using JPA/hibernate as the database-layer, so we use spring spring to create and inject the entitymanager to our DAOs, and set up transactional settings.
I've written swing UI's that are backed by spring.
cons
the startup can be slower but you have to have a large app for that to happen.
and a splashscreen is a good idea in those situations.
its easy to "overbean" or over-zealously make everything a bean, which gets messy.
pros
spring works fine behind a GUI.
it provides a lot of services you can use
the obvious dependency injection and decoupling
a global event system, simpifying some of your own event listeners, for events that will only ever be fired by one source
resource accessing
database access is eays in 2 tier apps
rpc for 3 tier apps is easy
There are other services the spring application context provides, but that I haven't used.
If you go this direction, also look into the java-based configuration for spring, which is new in 3.0. I find that helpful as well, as it makes my spring configuration type-safe.
One disadvantage of using Spring in a Swing application is that Spring DI will make startup slower.
well one would be , if you ever decide to migrate to a web app , all you need ( well almost) to change would be the views. That's the beauty of MVC applications.
I'm looking at this java web application that is using hibernate, jsp's, and spring framework. (from what I can tell!)
the file layout is like this:
classes/com/example/project1
inside project1
/dao
_entity_Dao.java
/dao/hibernate/
_entity_DaoHibernate.java
/factory
DaoFactory.java
DaoFactoryImpl.java
/managers
_entity_Manager.java
/managers/impl
_entity_ManagerImpl.java
/model
_entity_.java
/service
_xxxx_Service.java
/service/impl/
_xxxx_ServiceImpl.java
Have you guys read about this sort of layout somewhere? Is it considered best-practice?
What is the difference between a Factory and a Manager and a Service? (high level)
For typical layout of an application built with Spring I'd look at the example web applications that ship with it (meaning Spring).
Using things like DaoFactory is definitely not be a best-practice, the Daos should get injected instead. In general you should not need factories with Spring except for some unusual cases. Injecting is done when the web application starts up, spring reads the configuration information and constructs all the objects and plugs them in according to configuration xml and/or annotations (this is assuming singleton-scope for your objects, which is usual for stateless things like daos and services, things scoped as prototypes get new copies created as the application asks for them).
In Spring applications a service is similar to a Stateless Session Bean, it is a transactional layer encompassing application logic for a use case. So if your user takes an action that has the effect of causing several different tables to get updated you can inject the daos into that service, have a method on that service do the updates on the daos, and configure Spring to wrap that service in a proxy that makes that method transactional.
I've seen manager used as another name for what I described as service. Here I don't know what they're doing with it.
I don't like the idea of combining your interfaces and impls in one project. Just because you want to consume the interface doesn't mean you want to consume the impl and it's cumbersome transitive dependencies. The main reason is because there will be more than one impl (hypothetically, i.e. JPA/JDBC/Hibernate, or Axis2/CXF, etc.). The interfaces should not be bound to the implementation, otherwise the point is lost. This also allows for easy dependency injection as the impls simply reside on the classpath, then something like a Proxy or Spring (e.g.) can inject the implementations.
In all likelihood, all you need is a:
Interface Project
dao
EntityDao
types
Entity
HibernateImpl Project
dao
EntityHibernateDao
src/main/resources/
EntityMapping.cfg.xml
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.).