Get Spring Bean definitions without initializing Context - java

I am developing a code analysis plugin and a user project may contain Spring definitions.
Analyzing a source class, I need to get information about beans (more specially, which class actually implements an injected interface). Of course, I can take this information from Context. However, starting a context may cause to some side effects (like some db configuring or actions in post processors) in users code that is unacceptable.
How can I get the required information without initializing Context?
How can I start Context in "safe" mode to avoid or at least minimize side effects?

Related

Can you stop Spring Cloud rebinding/reloading POJOs annotated with #ConfigurationProperties?

If you annotate a POJO with #ConfigurationProperties, it allows you to easily load properties from a (yml) properties file and make them available at runtime.
However, when Spring Cloud is on the classpath, the behaviour changes somewhat: the POJO is now re-bound whenever an EnvironmentChangeEvent is fired. That's great, unless you have manipulated the properties at app startup somewhat - those changes can now get overridden at any point.
Is there a way to stop that from happening (e.g. by adding another annotation to that class to say "never" rebind)?
In particular, I have a #SpringBootTest-annotated test class where a library I use is dynamically generating a port number. I'm accessing that number in my #Before method, and want to "inject" it into the POJO, so the app under test picks it up and connects to that port (i.e. the equivalent to -Dmy.port=0000 at JVM launch). What would be a better way to achieve that (if switching off the rebinding and just assigning the value to the right field doesn't work or is the wrong approach)?
I have tried setting it via System.setProperty(), unsurprisingly with little success, or to add it via adding a new PropertySource to the ApplicationContext, and by using the TestPropertySourceUtil.addInlinePropertiesToEnvironment() - all to no avail...

Spring integration and changing data routes

I'm reading through Spring Integration documentation and I still can't get into one thing: does Spring resolve all dependencies and make that automagic IoC dependency injection at compile time or at runtime?
I believed that it is runtime job to wire available components together in a data route from gateway to some data endpoint (e.g. DB). But since most of examples are made using DSL syntax in java, it seems that it's a compile time job.
So, glueing together beans in a data highway can be made only at compile time?
Summing up my comments here :
1) Spring IOC container manages beans from its creation till destruction. What this means is the beans are ready in sort of a bucket, which is a ready to use application. Thus, it is necessary to create the contents of the bucket at compile time, rather then runtime. This does not include hot-swapping of beans.. I hope this is what you were looking for.
2) You can create as many routes as you want, those all beans will be put in the container.... And as far as I understand, you cannot just change your source code and synchronize it with already running one, you have to atleast do a graceful restart. There is a bottom line to this, Spring must see if all beans are properly autowired, no circular dependencies, and there is no expectation of source code during run time. Sure you can get your beans via RMI, but that doesn't count as you have declared it already. So yes, compile time it is
The java DSL syntax is simply a different way of defining a flow definition (a series a bean definitions). The beans are still created and wired together during application initialization (runtime).

Hacking a singleton with classloaders - Multiton in a Java web app

I am creating a web front end using an existing back end containing several singleton classes. The DataStore is initialized by passing a user object into it, which is fine in a desktop application environment where the app is launched once on each machine, but will not work in a server side application designed to cater for multiple users.
The database guys are reluctant to change the service layer and remove these singletons to allow an instance per user, or allow a single instance of a service layer object to serve multiple users. This is with good reason, the desktop app has been in use for 10 years and changes could have serious side effects for the desktop app.
I have been asked to investigate using classloaders to create multiple instances of the singletons. I am not comfortable with this idea at all, hacking singletons seems like bad practice, but changing the service layer could take months of work.
I have tested this out already by putting two identical WAR files of my app (with different file names) into Tomcat. Tomcat creates a classloader for each webapp and they worked just fine separately. I only encountered problems when the singletons used System.setProperty/System.getProperty, which is to be expected as the System class comes from a classloader much higher up in the tree.
To get this separation within a single webapp, it starts to get a bit complicated. It seems I would have to create a different classloader for each session, and use the classloader to load either all the classes in the whole service layer or just the ones which are singletons and their dependencies.
The problem comes when I'm thinking about how to use these objects in a session in a servlet. Because each Servlet has a single instance within a Tomcat, getting objects from the session and casting them will not be straightforward. Eg, to get a DataStore object from the session, I would have to cast it to the correct DataStore class loaded by the correct ClassLoader, since a single class loaded by two different ClassLoaders counts as two completely separate classes.
I have read that using ClassLoaders can cause all sorts of problems with memory leaks if they are not used carefully, and from the sounds of this, if I have 500 users, that is a lot of classloaders and classes loaded by classloaders. Won't I then have also have issues with PermGen?
I suppose from this large explanation, I really have 4 questions:
Hacking a singleton with classloaders in a webapp. Creating potentially hundreds of instances of the same classes designed to be singletons. Is that a terrible idea? So terrible I shouldn't contemplate it?
What is the best way to implement this if I absolutely have to?
How do I cater for casting in a Servlet, if I want to get and set objects into a session?
Will I end up with issues with memory leaks, and PermGen space?
I would really appreciate any suggestions. Thanks :)
It's not ideal, but I don't think it's terrible. In practice, it's not much worse than loading multiple versions of the same class (even without singletons), and that's becoming increasingly common in complex application server environments, particularly those with OSGi.
It's hard to say which approach is best, but to begin with, I would start by creating child class loaders of your web application class loader. Arrange to load implementation classes in the child class loaders (i.e., the ones with the singleton), and it possible, have the implementation class implement an interface that is loaded from the web application class loader.
By loading the interface from the web application class loader. This is basically the same approach that the application server itself is using to invoke your HttpServlet: the interface is loaded by the server, so it can refer to it directly, but the implementation is in a child class loader for your application. You're just creating a secondary layer of interface/impl split for your own convenience.
You'll end up with memory leaks if you store references to the child class loader (or its loaded classes, or instantiated objects from those classes) in a "parent" class loader (e.g., if the singleton registers an MBean, which causes it to get referenced in a JVM-wide object), but that's no different from if you weren't creating child class loaders. If you're dynamically creating/destroying these singletons (thus child class loaders), you'll have to take care that you don't retain references to those child class loaders (or classes/objects) longer than necessary. PermGen is probably more problematic. If you can run with Java 8, that's gone away; otherwise, you might have to increase the default PermGen size depending on how many of these class loaders/singletons you need to create.

Load spring context in phases

This is one of those strange questions where people would ask - why?
So I will start with why I would like to do this and then go into the issue. I would like to have more control over how the spring context is loaded. For example, I do not want to load the domain and web-api at the same time. That would make the resources available before their dependencies are ready.
There might also be that I need to check the state of something before I can continue this process. So to say, there will be sequential order between modules/contexts. Maybe not just booting but also in shutdown.
So the issue is that I can't find any information on how to load the domain-context, then when that is finished I would check the state and lastly load the api-context. I would like to do all of this from java-code as I need to control the flow of the start up. I have basics working with SpringServlet loading the web-context. What I have not found any information on is if it is possible to load a context, wait and load another context that refers to the first one.
It might be good to know that I am not using JavaEE nor a container. I am only using embeddded Jetty with servlet and spring. So is there a way this can be done?
I'd suggest to consider following:
Read SmartLifeCycle and Phased for extension points on the order of application context life cycle management. The idea is that you have your top-level important beans implement the interfaces such that the standard application context initialization will be also handled to those beans in the order that you customize.
Break your application context XML files into smaller pieces. Use <import /> in the ones that depend on a higher/lower context.
Use depends-on attribute on your mission critical beans to ensure the dependencies.
Use InitializingBean on the ones that you need to make sure a dependency is satisfied for the current bean after it's initialized.
Consider lazy loaded beans and Lazy Proxy.
So the bean will be created only on first usage ...

Troubles with HTTP-MMO game in Java

I'm about to write a MMO, using HTTP-requests that are responsed with JSON.
I was writing it all in Java EE-style, hoping it won't be hard to port to Java EE than. But then I've found out that my static instance variables for a couple of sinletons weren't created properly - classloader made a bunch of them when calling SingletonClass.getInstance() from servlets.
I was totally desperate and thought adding #Singleton descriptions would help. But things weren't so easy. My classes simply not working while adding them with #EJB ClassName var. Context lookup doesn't work either.
I was trying developing in Eclipse, NetBeans, used Glassfish, tried to set it up, but nothing really helped. I do not know what to do and really desperate now.
All I need is just few classes, that work all the time application is loaded to handle game events and hold logged users data (which is distributed in non-EJB objects that hold user data, monsters and so on), some timed events for each logged user and ability to respond to HTTP POST requests with JSON. I even do not need the ORM, I wrote all queries by myself, but still... Something that had to work simply doesn't work out.
I'm aware that all that sounds messy and non-informative, but I do not know what to do - where is my problem? Maybe, I should fill web.xml, or use different port, or fly to the moon? Or just change programming language? Sorry for your time spent reading this.
UPD. Some application scheme parts. First two from package "server".
#Startup
#Singleton
public class DbWrapper
handles all database connections, DbConnectionPool is non-singleton class, which handles pool of java.sql.Conneciton.
#Startup
#Singleton
#DependsOn("DbWrapper")
public class World
is yet another class to handle all the in-game events, that holds HashMap of logged users. User and Monster classes are from package "entities" (User holds a list of monsters).
Package "servlets" hold HttpServlet descendants, annotated #WebServlet("/pathname"), that try to use
#EJB World world
for example. But such things as world.getUser(id_user) simply won't work.
As for JDBC - postgres jar is included in GlassFish domain's /lib.
As for JSON - I use org.json found here: https://github.com/douglascrockford/JSON-java
I've found out that my static instance variables for a couple of singletons weren't created properly - classloader made a bunch of them when calling SingletonClass.getInstance() from servlets.
First, you should show us the code for one of these singleton classes. You may have made a mistake in the implementation that causes this problem.
It is true that you can get what appear to be multiple instances of a (properly implemented) singleton class in a servlet framework. But in fact they are not what they appear to be. What is actually going on is that you have loaded the class from multiple classloaders, either because you have multiple webapps each loading the class, or because you are redeploying your webapp and the previous deployment is not clearing up properly.
So what can / could you do about this?
You could use a dependency injection framework to configure your webapp, and hence avoid the need for singleton classes.
You could continue using singletons, but track down why you are getting multiple instances, and fix that problem.
You should use singletons really rarely (best would be not to use them). As an alternative use application scoped beans (#Singleton beans should normally work - they should use instance variables though, not static ones).
With Java EE 6 you also can use CDI and thus you don't have to use EJBs if you don't need the additional features they provide (like automatic transaction demarcation, security etc.) or can live with adding those features yourself.
Additionally, you can use CDI in a SE application. Keep in mind though, that you need to define the scope for CDI beans (e.g. #Application, #Request etc.) otherwise the default scope (#Dependant) is used which causes the beans to be copied on every access.

Categories

Resources