Currently I am using mongodb with java. I don't want to reopen my connection to the datastore every time, so I thought I should make a static variable:
package Config;
import java.net.UnknownHostException;
import com.google.code.morphia.*;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
public class Config {
static String dbUrl = "url";
static int dbPort = portnumber;
static String username = "user";
static String password = "pw";
static String dbName = "dbname";
public static Datastore ds;
public static Datastore getDatastore() throws UnknownHostException,
MongoException {
if (ds == null) {
ds = connect();
}
return ds;
}
public static Datastore connect() throws UnknownHostException,
MongoException {
Mongo m = new Mongo(dbUrl, dbPort);
Datastore ds = new Morphia().createDatastore(m, dbName);
boolean con = ds.getDB().authenticate(username, password.toCharArray());// todo
return ds;
}
}
I would use it like this:
Config.getDatastore().doSomthing();
Beside those un-handled exceptions, is this the correct way of using a static variable?
Better would be making Config class as a singleton.
The given Config seems to indicate that this class should be a singleton, and if so, then using static variables for all members is fine. Will you have multiple Configs, or only one?
If Config isn't intended to be a singleton, then static isn't required in this case, or if so, only if it's ok to share your Datastore with every instance of your Config class. You'll achieve your goals with a simple - non-static - member variable, and you can still have, e.g. a getDataStore method. But each Config class will have it's own Datastore
Only use static if you want to also share that Datastore among multiple instances of your Config class.
is this the correct way of using a static variable?
well, your code seems to compile so as per the language its correct. As far as semantics are concerned the usage depends. it depends on the class in questions, the design you want to achieve.
I would personally go for a connection pool. If several connections are not required, i may go for a singleton if i need to maintain only one connection. If a single connection is not required i would go with a member variable.
In your case, it would depend on how you want to use the config class. In general design terms, what you have done is problematic for following reasons:
Everything is static in your class, it serves no purpose in terms of object oriented-ness.
You can not unit test this class unless you use powermock or some other framework.
what happens when someone calls connect() several times?
*Note: Singleton is an anti-pattern. Generally any global state is bad. I would avoid it as much as i can.
Related
I know that an instance of a class with a private constructor can be created using reflection but is there any way to make sure that the instance of the class can only be created within the same class using its own private constructor?
Let's take an example of a class Test, with a private constructor.
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Test
{
private Test() //private constructor
{
}
}
public class Sample{
public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
{
Class c=Class.forName("Test"); //specify class name in quotes
//----Accessing private constructor
Constructor con=c.getDeclaredConstructor();
con.setAccessible(true);
Object obj=con.newInstance();
}
}
My question is - is there any way to ensure that the instance of the class can only be created within the same class and not from outside using reflection or any other method?
There are several ways to prevent the creation - but it is hard to tell which one is appropriate for your use-case:
Throw an exception in the constructor
You can either unconditionally throw an exception - making it (near) impossible to instantiate an instance - or only throw under certain conditions.
Some conditions can be:
Inspecting the caller - using StackWalker for example.
Passing a "secret" passphrase to the constructor. JMH does this for example.
Use Java Modules.
As other modules can't deeply reflect into other named modules, Constructor.setAccessible will not work on your class outside of your own module.
Of course this restriction doesn't apply to your own module - but you should be able to control your own module ;).
Install a SecurityManager.
Prevents Constructor.setAccessible from returning successfully.
But the security manager is deprecated for removal, so I can't recommend it's use.
Note: Most of those solutions can be circumvented in some way. And it is sometimes possible to add additional defenses against that. But at the end, it'll become a game of cat and mouse.
One way you already mentioned in comments by using Exception & another way to do this is using Thread.currentThread()
package app.test;
public class Test19 {
..
private Test19() {
if (Thread.currentThread().getStackTrace()[1].getClassName() == "app.test.Test19") {
// initialize member fields etc.
} else {
throw new IllegalAccessException();
}
}
}
I'm fairly new to Vertx, And trying to find some realistic examples of database usage.
I have a Verticle that creates a shared database object (And a number of classes that handle routing, but I would like to use the shared database outside the main class, obviously I could pass the database object in other classes constructors, but I'm sure Vertx has some better way to do this.
public void start() {
...
this.postgreSQLClient = PostgreSQLClient.createShared(vertx, sqlClientConfig);
...
}
Does anyone have any Java Vertx examples with realistic implementations of a database?
Thank you in advance.
Use Dependency Injection. I have used Guice
Here's the example of it:
Main.java
//within main function where you have object of vertx
Guice.createInjector(new AppInjector(vertx));
AppInjector.java
//Create an Injector file and bind your injections
PostgreSQLClient postgreSQLClient = PostgreSQLClient.createShared(vertx, sqlClientConfig, "my-shared-client");
bind(PostgreSQLClient.class).annotatedWith(Names.named("DBClient")).toInstance(postgreSQLClient);
UserService.java
public class UserService {
#Inject
#Named("DBClient")
private PostgreSQLClient client;
}
You can find the source code here
Just specify a pool name:
if different clients are created using the same Vert.x instance and
specifying the same pool name, they will share the same data source.
So updating your example:
public void start() {
this.postgreSQLClient = PostgreSQLClient.createShared(vertx, sqlClientConfig, "my-shared-client");
}
Note that when doing this, the configuration provided in the first call will be used. Subsequent calls will simply return the existing client.
Hello everybody!
I have developed a JavaFX application to support my scientific work (molecular biology/neuropharmacology), implementing Neo4j, at the time Version 2.x.
Now, since Version 3 (using 3.1.0-M05) is out, I am switching over to Bolt protocol access of the Database, with the Driver (1.1.0-M01) interface. Some functions of my application still require Java API access though, so I cannot completely abandon the old code. I am using a singleton GraphDatabaseFactory to start up the database, like so
private static GraphDatabaseService instance;
private GraphDb() {
instance = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(new File(FilePaths.DATABASE_PATH))
.setConfig(ShellSettings.remote_shell_enabled, "true").newGraphDatabase();
}
public static synchronized GraphDatabaseService getInstance() {
return instance;
}
(Or, just the .newEmbeddedDatabase())But now, since Version 3, I also use a singleton Driver instance for the Bolt interaction, like so
private static Driver instance;
private GraphDbDriver() {
startLocalDb();
instance = GraphDatabase.driver("bolt://localhost");
}
private static void startLocalDb() {
//start database here?
}
public static synchronized Driver getInstance() {
return instance;
}
My question now, is this (since I gathered that using both at the same time can only breed complications): How do I use these two ways of communicating with the DB without them getting in the way of each other?
Can I somehow get the Driver to load "onto" the already created GraphDatabaseService singleton?
Thanks for reading!
So, for anybody who's interested, in Neo4j 3.x it is recommended to use 'User-defined procedures' to implement API commands (like, e.g., traversals) and then calling it (via CALL) from cypher.
In a Junit test, is it possible to test for variables in the main method?
My main method something like this looks like this:
package edu.blah.class.project1;
public class Program {
public static void main(String[] args) {
try {
int result = Utility.analyze();
} catch (Exception e) {
System.out.println("Error");
}
}
}
Is it possible to obtain the variable result in a JUnit class? Is the only way to make it a public variable? Thanks!
In a Junit test, is it possible to test for variables in the main method?
Err ... no. Unless you have a JUnit test that calls the main method explicitly, then the main method won't be called in a unit test.
Besides, the variable here is result which is a local variable, and there is no way to reach into a method to test some local variable. (Java simply doesn't allow it ...)
Is it possible to obtain the variable result in a JUnit class?
In this example, result gets the value of the call Utility.analyze(). There is no reason why a JUnit test could not do that too ... and thereby get the same value. (Or at least it could in this example.)
Is the only way to make it a public variable?
No ... see above.
However, if you are actually trying to test the value of result in the context of the main method, then you are right. The only way to get hold of the value would be to expose it as a static variable. It doesn't necessarily have to be public static though. (Indeed, if you were prepared to write do some "nasty" reflection you could even get your JUnit test to extract and test the value of a private static field.)
However, I think you are taking the wrong approach top this. Rather than trying to figure out how to reach into a static method (or any method), it would be better if you restructured the code to make it more testable. For example:
package edu.blah.class.project1;
public class Program {
public int run(String args[]) {
return Utility.analyze();
}
public static void main(String[] args) {
try {
new Program().run(args);
} catch (Exception e) {
System.out.println("Error");
}
}
}
With a small amount of restructuring (like this), you can make it a lot easier to write unit tests for all of the important functionality. You are left with the "problem" it is still hard to unit test the main method. However, you have reduced the method to the point that it is so simple that you can verify it is correct by visual inspection: unit testing main is now unnecessary.
No, local variables are allocated on stack and are not available outside the method.
Your wishing to check the local variable from test means that you probably should split your method into several smaller ones. Generally this is one of the principals of TDD - Test Driven Development.
Unit tests can call any accessible method, including the main method. Apart from it being recognized as an application entry point there is nothing special about the main method.
Regarding how to test your example, in the current state the local variable result cannot be accessed. Before resorting to all sorts of tricks to access it, ask yourself the question why you would want to test for it?
A unit test should check the contract of a method, which comprises of the input parameters, the return value and any side effects. Testable side effects are:
changing the state of the encompassing class
calling instances of classes that are fields in the class under test
Hard to test side effects are:
static calls
direct interaction with the environment like the file system, network, threads
behavior depending on system time
In most cases the situations that are hard to test can be avoided by refactoring your application, making it more testable.
However, in your example none of the above applies. The local variable 'result' is not used for anything. So in the current state of your application you don't have to (and cannot) test for its value.
When I use my imagination to guess what your application could/should be doing an extended and testable version may look something like this:
public class Program {
public static final String ERROR_MESSAGE = "Error";
// Utility modeled as a dependency to avoid static access
private Utility utility;
// a poor man's logger, better to use a logging framework like log4j
private PrintStream logger;
// 'business logic' extracted into a separate method to be tested
public void execute(String[] args) {
try {
// static access to Utility replaced with instance access
// passing the args to make testing more interesting
int result = utility.analyze(args);
// added logging of the result to make testing more interesting
logger.println(result);
} catch (Exception e) {
// Static access to System.out replaced with logger instance
logger.println(ERROR_MESSAGE);
}
}
// setters used for dependency injection
public void setUtility(Utility utility) {
this.utility = utility;
}
public void setLogger(PrintStream logger) {
this.logger = logger;
}
// application entry point does basic initalization and depency injection
public static void main(String[] args) {
// create application instance
Program program = new Program();
// inject dependencies
program.setUtility(new Utility());
program.setLogger(System.out);
// call application
program.execute(args);
}
}
And the unit test, using JUnit4:
import static org.mockito.Mockito.*;
import org.junit.*;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.*;
#RunWith(MockitoJUnitRunner.class)
public class ProgramTest {
// #InjectMocks creates an instance and injects any specified mocks
#InjectMocks
private Program instance;
// #Mock creates a mock instance, which can be used to specify behavior using when() and verify access using verify()
#Mock
private Utility utility;
#Mock
private PrintStream printStream;
// #Test indicates a test method in JUnit4
#Test
public void testExecuteHappy() {
// SETUP
String[] args = new String[];
int expectedResult = 42;
// specify behavior of the Utility mock to return the expected result
when(utility.analyze()).thenReturn(expectedResult);
// CALL
instance.execute(args);
// VERIFY
// check that utility.analyse() was called with the args
verify(utility).analyze(args);
// verify that logger.println() was called with the expected result
verify(logger).println(expectedResult);
}
#Test
public void testExecuteError() {
// SETUP
String[] args = new String[];
// specify behavior of the Utility mock to throw an exception
when(utility.analyze()).doThrow(new Exception("test exception));
// CALL
instance.execute(args);
// VERIFY
// check that utility.analyse() was called with the args
verify(utility).analyze(args);
// verify that logger.println() was called with the error message
verify(logger).println(Program.ERROR_MESSAGE);
}
}
Typically dependencies require additional configuration like which database to access, connection pools etc. In a larger application dependency injection would be done by a framework like Spring or CDI rather than the main method.
Here are the Maven dependencies needed for this:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
</dependency>
</dependencies>
Add these to your pom.xml. If you don't use Maven, download these .jar files and add them to the class path used for compilation:
Junit 4.11
Mockito core 1.9.5
Note: I didn't compile or test the above code so there might be small typo's
I've got some code I'm deploying to Google App Engine - Java (GAE/J) that makes use of the URLFetchService. I'd like to use JUnit to test this code. Per the testing documentation, it appears I should have a test that uses their LocalURLFetchServiceTestConfig class ROUGHLY as follows:
public class MyRemoteServiceTests {
private static final LocalURLFetchServiceTestConfig urlConfig = new LocalURLFetchServiceTestConfig();
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(urlConfig);
#Before
public void setUp() throws Exception {
service = new SampleService();
helper.setUp();
}
#After
public void tearDown() throws Exception {
service = null;
helper.tearDown();
}
#Test
public void testThatCallsCodeThatUsesUrlFetch() {
Object data = service.getRemoteDataUsingUrlFetch("foo", "bar");
Assert.assertNotNull(data);
}
}
I'm finding that this test continues to fail despite using the "helper" as suggested in the GAE/J documentation on testing: "The API package 'urlfetch' or call 'Fetch()' was not found.".
I was assuming that using the "helper" would somehow setup the GAE environment such that when I call URLFetchServiceFactory.getURLFetchService() from within my getRemoteDataUsingUrlFetch method, the interface returned would be an instance of LocalURLFetchService that would just "work" but that seems NOT to be the case.
How can I test this code?
Am I missing something? (I'm pretty new to GAE...)
Do I have to refactor my getRemoteDataUsingUrlFetch so that it doesn't use URLFetchServiceFactory.getURLFetchService() because that makes it untestable locally??? (That sounds like it would really suck...)
Any help/suggestions much appreciated!
Actually, it turns out my problem was failure to include two additional jars that ARE mentioned on the Local Unit Testing page of the documentation. RTM FTW!
appengine-local-runtime.jar
appengine-api-stubs.jar
afaik, the LocalURLFetchService doesn't configure the GAE like you expect. It is more of a way to fetch URL from the local dev and then process the contents however. (Similarly even the LocalDatastoreService and LocalMemcacheService operate on isolated spaces within the test environment)
One way to test your code is to refactor the getRemoteDataUsingUrlFetch() to take maybe the contents of the Url response. somewhat like,
URLFetchResponse resp = LocalURLFetchService.fetch(status, request)
getRemoteDataUsingUrlFetch(foo, bar, resp)