In Java EE how can I use a variable anywhere in code without passing it down as a parameter?
Something similar to a public static variable... but a static variable is always the same for all the requests... What about a "static" variable but for the single request?
Is it possible?
Here is a little example:
I have:
protected void doGet (...)
{
Model m = Model.GetById (...);
}
public class Model
{
private String descrition;
private Market market;
private List<SparePart> spareParts;
public Model GetById ()
{
Model m = new Model ();
// get info from db using the language
this.market = Market.GetById (...);
this.spareParts = SparePart.GetByModel (m);
}
}
public class SparePart
{
private String description;
public List<SparePart> GetByModel (Model mo)
{
// get info from db using the language
}
}
public class Market
{
private String descrition;
public Market GetById (...)
{
// get info from db using the language
}
}
Both make queries to the database and retrieve informations using the language of the client... How can I set the language variable so i don't have to pass it to the methods that use it?
The anguage variable is just an example, it may happen with other variables
There are dozen ways to pass your data through execution flow in JaveEE applications. Let's assume you need to pass data within one application boundary.
Of course you can use public static final constants.
You can use public static variables, but take into account that EE
environment is extremely multithreaded. So use atomic wrappers
(AtomicInteger, etc).
You can use producers
While single request scope (http (rest) -> interseptor(s) -> bean(s)
-> response) you can use ThreadLocal
Of course you can use Stateful or Singleton beans You can use CDI
Events
If you are using Payara Server (for now the only has JCache spec
preview) you can use JCache to share your data among any
application or along the cluster as well
If you need to share your data between servers you can expose your business methods on #Remote interfaces and or share/publish/consume using JMX.
The concrete choice should depend on your App business logic.
You can set and get attributes on your ServletRequest object.
request.setAttribute("someName", someObject);
Object someObject = request.getAttribute("someName");
See the javadoc here.
Alternatively, you could use CDI (or another DI framework) and define one or more #RequestScoped objects that you can then #Inject in the places you need them.
Although not passing parameters is not a good idea in the first place, if you 'MUST' find a solution and if it matches your design, how about using inner classes? That way you declare the class variable as non-static and you can always access it from the inner classes.
Related
I'm trying to develop a simple application using OSGi framework. My question involves an "utility bundle" available in the framework: let me explain with a pretty verbose example. At the moment I'm trying to build an event my bundle will send.
From what I understood, what i need is to do something like the following (event admin felix):
public void reportGenerated(Report report, BundleContext context)
{
ServiceReference ref = context.getServiceReference(EventAdmin.class.getName());
if (ref != null)
{
EventAdmin eventAdmin = (EventAdmin) context.getService(ref);
Dictionary properties = new Hashtable();
properties.put("title", report.getTitle());
properties.put("path" , report.getAbsolutePath());
properties.put("time", System.currentTimeMillis());
Event reportGeneratedEvent = new Event("com/acme/reportgenerator/GENERATED", properties);
eventAdmin.sendEvent(reportGeneratedEvent);
}
}
Now, since an OSGi application may have lots of bundles, I thought to create a subclass of Event for every bundle (eg. I have a bundle named "BundleExample"? Inside it's exported classes there will be a "BundleExampleEvent"). I know this doesn't add any information since you can know which event you received by looking at "topic", but please bear with me for the moment.
Now, the Event constructor needs a topic and a Map<String, Object>. However, to "simplify" the event constructor, I would like to have only the topic and the list of parameters to put inside the map. For example here's what might be a BundleExampleEvent class:
public class BundleExampleEvent extends Event{
private int importantVariable;
public BundleExampleEvent(String topic, int importantVariable) {
super(topic, Utils.toMap("importantVariable", importantVariable));
//here toMap is static
}
public int getImportantVariable() {
return this.importantVariable;
}
}
Ok, please note the Utils.toMap: it's a function that allows you to convert a sequence of String, Object into a Map. Ok, now Utils is an example of a utility class (stupid, useless but a utility class nonetheless). In the spirit of OSGi I want to make this utility class a bundle as well: my thought would be to start this Utils bundle at framework boot and then whenever I need one of its utility I want to fetch a reference via #Reference annotation.
This can work greatly in any bundle interface implementation, like this:
#Component
public class BundleExampleImpl implements BundleExample {
#Reference
private Utils utils;
#Override
public String sayHello() {
return this.utils.fetchHello();
//another useless utility function, but hopefully it conveys what i'm trying to do
}
}
But what about other classes (i.e. called by BundleExampleImpl during its work)? For example what about the BundleExampleEvent? I need to call it from sayHello method and I want to use this utility also inside that class in order to compute the Map! In the previous example i used a static function, but I would like to use the reference of Utils OSGi gave me.
Of course I could add a parameter inside the constructor of BundleExampleEvent in order to satisfy the link but I rather not to do it because it's pretty silly that something would depend on an "utility class"; my question are:
Is this the only method available if I want a "utility bundle"?
Or can I do something weird like adding a reference of Utils also in my BundleExampleEvent; i.e. something like this:
public class BundleExampleEvent extends Event{
#Reference
private Utils utils;
private int importantVariable;
public BundleExampleEvent(String topic, int importantVariable) {
super(topic, Utils.toMap("importantVariable", importantVariable));
//here toMap is static
}
public int getImportantVariable() {
return this.importantVariable;
}
}
Or maybe the whole idea of having an "utility bundle" is just pure trash?
Thanks for any reply. Hope I could convey my problem in the clearest way
I don't think there is any point in Utils being a service. Things should only be a service if they can conceivably have multiple implementations. In your case, the consumer of the Util functionality only ever wants a single implementation... the implementation is the contract.
I don't even think the utils code should be in a bundle. Just make it into a library that is statically linked into the bundles that need it.
In your case the Utils utils would be an OSGi service. Then you want to use this service inside an object that is not a service like BundleExampleEvent.
What you could do is to create a service that creates BundleExampleEvent instances and feeds it with an OSGi service. Kind of like a factory as a service. The problem with this is that services in OSGi are dynamic. If the service needed by the BundleExampleEvent instance goes away then the object would have to be discarded. So this only works for short lived objects.
In the eventadmin example a different solution would be to not use a special event class but instead create a service that has a method to send such an event. Then all the magic would happen inside this method and the result would be an event without further logic. You could also inject EventAdmin into that service using DS.
This works very well in OSGI but has the disadvantage of the anemic domain model (http://www.martinfowler.com/bliki/AnemicDomainModel.html).
I am not sure which variant to prefer.
I need to implement a solution as part of Test framework & I am considering singleton pattern for reasons explained below. However, I am not able to achieve my intended solution & therefore would need some suggestions/inputs on possible implementations.
Problem Statement :
I have a environment (env of the product I am testing) configuration properties file which I want to load & make the value of the parameters accessible globally to the test framework.
I figured using the singleton pattern because these properties are one-time values (should report an exception if tried to initialize more than once), should be available globally & have an one-point access to the methods.
However, the list of properties/parameters is really long & therefore it's wise to break it into modules (classes). For the below explanation, I tried with composition.
For e.g.
public class Configuration {
private static Configuration configObj;
private static Database dbDetails;
private static Machine macDetails;
//...
//... many more modules
public static synchronized void createInstance(Properities envProps){
//Should create only one instance of Configuration
// and should also initialize Database & Machine objects.
}
public static Configuration getConfigObject(){
return configObj;
}
}
public class Database {
private static String dbConnectString;
public Database(String dbcs){
dbConnectString = dbcs;
}
public static String getDbConnectString(){
return dbConnectString;
}
}
public class Machine {
private static String hostname;
private static String loginUsername;
public Machine(String hostname,String loginUsername){
this.hostname = hostname; //It may include some trimming/cleaning
this.loginUsername = loginUsername;
}
public static String getHostName(){
return hostname;
}
}
PS: Just a sample typed-in code for the understanding of my problem statement.
Expectation : The expectation now is that when trying to get the hostname, I should have a single point of access via Configuration static object (assuming that I have initialized all member variables successfully) i.e.
String hostname = Configuration.getHostname();
OR
String hostname = Configuration.getConfigObject().getHostname();
Current Issue :
How to create one static object that will refer to all methods using either composition or inheritance (Conceptually, composition would be the right approach).
Multiple Inheritance would have solved the issue but Java doesn't support so ruled out. Cannot consider Interfaces either because overriding all methods is tedious & lengthy & the parameters/methods will keep changing over-time.
All suggestions are welcome even if it requires to scrap this design pattern & try something different.
You will not be able to "automatically" delegate static calls to modules. And even if the calls were not static, as you stated, Java does not support multiple inheritance.
Option 1:
Have your main Configuration class provide static methods that return instances to your modules. Whenever you want to read a configuration entry, first get the module instance, then query the entry itself:
Configuration.getDatabaseConfiguration().getServerName();
This method has the advantage that it is very clear which part of your configuration you are referring to. If you would just use Configuration.getServerName(), you cannot distingish whether you want to retrieve the database's server name, or the webserver's.
Option 2:
If you are able to use Java 8 and your configuration is large, but very simple (statically known at compile time or extractable from very few instances), you could consider using the new default interface methods (https://blog.idrsolutions.com/2015/01/java-8-default-methods-explained-5-minutes/).
You would then create an interface for each module, where all getters have default implementations. Your main configuration class would implement all the module interfaces without overriding any of the methods. This way all configuration entries can be queried from one object, but you still have to obtain this object by a static method. This is as close to multiple inheritance as you can get. I would definitely recommend option 1 though.
I have multiple modules with service interfaces binding to their corresponding types and I am able to get an instance by using
injector.getInstance(MyServiceInterface.class)
I would like to retrieve the instance using
injector.getInstance("MyServiceInterface")
i.e. a string literal instead of the class type
How can I achieve this ?
To elaborate my question further - I can retrieve the Class object from the string literal using a Class.forName(literal) call and then use it to retrieve the instance with a injector.getInstance(clsInstance) .
After retrieving the instance which I receive in my base service type interface I need to use reflection to invoke the method of the service object.
so Service serv = injector.getInstance(MyCustomService.class)
Now I need to invoke myCustomMethod() present in MyCustomService through reflection since this invoker is generic and is intended to work with multiple services without being aware of their actual type.
I will also need the Method interceptors configured on the service interfaces to be invoked transparently when I invoke the method on this instance reflectively.
While I'm not certain if there's functionality for that built into Guice itself, you could try getting the relevant Class<?> object yourself.
Something along the lines of:
Class<?> myServiceInterfaceClass = Class.forName("path.to.MyServiceInterface");
injector.getInstance(myServiceInterfaceClass);
This does however require that the current Classloader can access that specific class, etc.
This can't be done within Guice... because it can't be done, period! Think about it, let's say you have two of the same class name in different packages. Which class would you instantiate?
So at the very least the String would have to have the fully qualified class name, e.g. instead of Integer, it would have java.lang.Integer.
However, if you know which classes you want to support in advance, you can use a MapBinder.
Tweaking their example to match your use case:
public class ServiceModule extends AbstractModule {
protected void configure() {
MapBinder<String, MyServiceInterface> mapbinder
= MapBinder.newMapBinder(binder(), String.class, MyServiceInterface.class);
mapbinder.addBinding("MyServiceInterface").to(MyServiceImpl.class);
bind(MyServiceInterface.class).to(MyServiceImpl.class);
}
}
Now you can inject like this:
class ServiceManager {
#Inject
public ServiceManager(Map<String, MyServiceInterface> services) {
MyServiceInterface service = stacks.get("MyServiceInterface");
// etc.
}
}
Please note when you call inj.getInstance() you do have to know the return type of the Object you're trying to create, unless you are planning on doing:
Object foo = inj.getInstance(myString);
I am writing a web service and one of the operation in service is getShortURL(String longURL). In this method I first check whether longURL exists in database, if yes, return it otherwise create a shortURL, insert it in database and return to client.
My confusion is how to organize and name my classes. Apart from the web service class, right now I have 3 classes:
URLData: It just has URL attributes and getters and setters.
MongoDB: It connects to database(right now connection attributes are hard-coded in it), inserts in database, and retrieves raw string from database.
MongoDBUtil: This class has again insert(URLData) method, it calls MongoDB.insert() to insert into database. Also has retrieveURLData which in turn calls MongoDB equivalent method to do the actual job.
Web service method sets URLData setters and calls MongoDBUtil.retrieve or insert.
I am thinking that URLData class should be named URLDataBusinessObject and along with setters and getters it can have insert, update and delete methods.
MongoDBUtil can be renamed to UrlDAO and it can have different kinds of retrieve methods.
MongoDB is more kinda Select query class, not sure how to design and name it.
Please advise
URLData is fine. Don't bloat your class name with long irrelevant words. If you want to make clear that this is a business object, create a package like com.yourcompany.yourproject.bo for example, then put your URLData class in there.
Yes, UrlDAO is more specific than MongoDBUtil. You can create a com.yourcompany.yourproject.dao package for it.
Looks fine for me. However if you use some kind of framework (e.g. Spring) you don't have to create your own class to hold the database connection configurations.
I suggest you google for some tutorial on the topic, you will learn both how to use the technology and how to name/orginize your classes.
This question might be suited more for http://programmers.stackexchange.com.
Nevertheless: yes, I would change the naming.
1) URLDataBusinessObject No, never. You're adding 14 characters to a classname without adding any value. URLData was just fine.
2) You should change the naming of your DAO classes to be non-DB specific, unless you explicitly have an architecture aiming at multiple databases and the DB-specific classes perform DB-specific tasks.
I'm assuming this isn't the case and thus you should give it a more general name.
Persistence can be just fine, DAO as well, anything that shows the intended usage without going into specifics is eligible.
3) MongoDBUtil is your interface to the persistence layer, it's not a utility class in heart and soul. What's the purpose of this class? If all you do is chain the method call to MongoDB you might as well drop it and go straight to the latter.
To create a simple layered design build interfaces for all the persistence specific operations and interfaces for all the domain objects. Then code against those rather than their concrete implementations. That way it's easy to swap out a mongo persistence layer for a different one, functionality is organised so that others can easily understand it and can also test against interfaces rather than concrete implementations. You'd have something like:
URLData interface
URLDataDTO class (used in the business layer)
Persistence interface
MongoPersistence class (used in the persistence layer)
My current project does something similar and also works with Mongo. The persistence layer interface has methods like "void put(URLData)". When called the Mongo implementation constructs a new MongoURLData from the URLData passed in, extracts the DBObject then persists it. Methods like "URLData get(String id);" work the other way around. The Mongolayer queries the database and creates new URLDataDTO objects from Mongo DBObjects. The web service is then responsible for serialising/deserialising DTO objects that are sent to or received from client applications.
My Mongo Domain objects all inherit from something this:
public abstract class MongoDO<T extends Object> {
DBObject dbobject = null;
public MongoDO(T dto) {
this.dbobject = new BasicDBObject();
};
public MongoDO(DBObject obj) {
this.setDBObject(obj);
};
public abstract T toDTO() throws StorageException;
public DBObject getDBObject() {
return dbobject;
}
public void setDBObject(DBObject obj) {
this.dbobject = obj;
}
public ObjectId getIdObject() {
return (ObjectId) this.getDBObject().get("_id");
}
public void setIdObject(ObjectId id) {
this.getDBObject().put("_id", id);
}
protected String getField(String field) {
if (dbobject.containsField(field) && dbobject.get(field) !=null) {
return dbobject.get(field).toString();
} else
return null;
}
protected void setField(String field, String value) {
dbobject.put(field, value);
}
}
An example Mongo implementation would be:
public class MongoURLData extends MongoDO<URLData> implements URLData {
private static final String FIELD_SHORT_URL = "surl";
public String getShortUrl() {
return getField(FIELD_SHORT_URL);
}
public void setShortUrl(String shortUrl) {
setField(FIELD_SHORT_URL, shortUrl);
}
public URLData toDTO(){
URLDataDTO dto = new URLDataDTO();
dto.setShortURL(getShortURL);
return dto;
}
}
I need to instantiate few classes through the Java reflection api and invoke 'a' method (method invocation not through reflection) in the instantiated class. I know the reflection do impact the application performance, but I am not very sure how much it hits on the web-environment! Like the Struts framework that instantiates the Action classes using the reflection, my framework too gets the class name as string configured in the file, which I read and instantiate on different requests. How about the idea of having only one instance per class and invoke its method for every requests?
example,
package com.app.events;
public class event1 implements iEvent {
public event1() {
}
public void doprocess(Object info) {
// do necessary events
}
}
package com.app.events;
public class event2 implements iEvent {
public event1() {
}
public void doprocess(Object info) {
// do necessary events
}
}
config.xml
<events>
<event>com.app.events.Event2</event>
<event>com.app.events.Event1</event>
</events>
// servlet init
String clazName = parseXMLFile(); // not every time but only once, I have the bean
Class claz = Class.forName(clazName);
// how about this?
// I save this instance for later requests
events.put(request.getParameter("event"), claz.newInstance());
// later requests,I retrieve the event from the map and invoke its method,
// just a rough code...
events.get(request.getParameter("event")).doprocess(info);
First of all, start by respecting the Java naming conventions. Classes are CamelCased and methods are camelCased.
Using a single instance is perfectly fine. That's what servlets do, as well as Struts1 actions, and Spring beans (by default) for example. But this should be documented, because it forces every implementation of your interface to be thread-safe (preferrably, by being stateless), unless your framework makes sure only one thread uses each instance at a time, which would considerably reduce the performance of your application.
Creating many instances used to be slow, many years ago. It's not anymore now, so I would create a new instance every time, unless having a single instance is important (because initializing an instance might be slow).