I'm running a long running web service via Jetty/CometD, and I'm using the Redisson library for connecting to redis. I'm using a Singleton pattern for getting my RedissonClient/connection and I am not sure if that is the best way to go.
Class looks like this:
public class RedisClient {
// singleton instance of our RedisonClient/connection
private static RedissonClient _redissonInstance;
public static String REDIS_HOST = "my.redishost.com:6379";
private static RedissonClient setupRedis() {
org.redisson.Config config = new org.redisson.Config();
config.useSingleServer()
.setAddress(REDIS_HOST)
.setConnectionPoolSize(200);
return Redisson.create(config);
}
public static RedissonClient getRedis() {
if (_redissonInstance == null) {
_redissonInstance = setupRedis();
}
return _redissonInstance;
}
public static void setRedisHost(String redisHost) {
_logger.warn("Setting REDIS_HOST to: " + redisHost);
REDIS_HOST = redisHost;
}
}
I would say that this is a bad idea. I don't think singletons are a good idea in general but even so this is not a good way to do it. Your code is not thread-safe and it seems as if you want to support multiple hosts.
If you really don't want to pass your redis client around to every component and your host is not going to change and want something quick and dirty try this:
public class Redis {
public static final RedissonClient CLIENT;
static {
Config config = new Config();
config.useSingleServer()
.setAddress("my.redishost.com:6379")
.setConnectionPoolSize(200);
CLIENT = Redisson.create(config);
}
}
This has the benefit of being thread-safe without having any synchronization when getting the reference.
Related
I'm a bit sceptic of this code, since it kind of violates YAGNI. I need some public static fields for my service class, but usually it's a bad design when you have those in your service bean, so I created an interface for that service, but I'm not sure it's the right choice. Should I have those fields in service class?
public interface IYouTubeServiceBuild {
/**
* Define a global instance of the HTTP transport.
*/
public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
/**
* Define a global instance of the JSON factory.
*/
public static final JsonFactory JSON_FACTORY = new JacksonFactory();
/**
* Define a global variable that identifies the name of a file that
* contains the developer's API key.
*/
public static final String PROPERTIES_FILENAME = "youtube.properties";
}
#Service
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class YouTubeServiceBuild implements IYouTubeServiceBuild {
#Getter
private Properties properties;
/**
* Define a global instance of a Youtube object, which will be used
* to make YouTube Data API requests.
*/
#Getter
private YouTube youtube;
#PostConstruct
public void init() {
properties = new Properties();
youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, request -> {
}).setApplicationName("youtube-search-demo").build();
//etc...
}
}
}
Above service class is then used in other service as follows:
#Service
public class YouTubeApiService {
#Autowired
private YouTubeServiceBuild serviceBuild;
public List<SearchResult> searchYouTube(String searchQuery) {
List<SearchResult> searchResults =
executeSearch(searchQuery, serviceBuild.getProperties(), serviceBuild.getYoutube());
//etc...
}
If the question is whether its possible to set public static fields in Spring managed bean - then yes, its possible, although I completely agree with you that its a bad design.
Leaving alone spring, putting constants in the interface so that the implementations of the interface will be able to access them is considered a code smell because all the implementations (assuming there are many) now can behave differently because some constant changes, or even worse - won't compile anymore if the constant is removed (what if not all the implementations are in the project).
Much better approach is creating a class of constants:
public class YouTubeConstants {
public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
public static final JsonFactory JSON_FACTORY = new JacksonFactory();
...
}
In the class that needs an access to these constants you can use YouTubeConstants.HTTP_TRANSPORT (or even shorted with static imports).
Now as for the presented design, let me propose an alternative:
The class YouTubeApiService basically needs an access to YouTube object only, it needs it to perform queries. No need for YouTubeServiceBuild intermediate object, no need for connection properties), IMHO it only complicates the code.
You can do something like this:
#Service
public class YouTubeApiService {
#Autowired
private YouTube youtube;
public List<SearchResult> searchYouTube(String searchQuery) {
List<SearchResult> searchResults =
executeSearch(searchQuery,youtube);
//etc...
}
}
Looks much better, doesn't it?
Now in order to create a youtube object, you need some code that goes a little bit beyond the regular "new". You can use a Configuration for this:
import static YoutubeConstants.*;
#Configuration
public class YouTubeConfig {
#Bean
public YouTube youtube() {
return new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, request -> {
}).setApplicationName("youtube-search-demo").build();
}
}
In this implementation there is no need in a YouTubeBuilder at all
One more things to consider:
It seems that you're trying to load some properties by yourself, notice, spring can to it alone.
I haven't seen any real usage of these properties in the code presented in the question, so I can't provide the working example, but please make sure you understand how to load properties in spring, you might inject the already-loaded properties into the youtube method in the configuration.
The general problem I am trying to solve is this. I have a solution, but it's very clunky, and I'm hoping someone knows of a more orderly one.
Dropwizard offers a JUnit TestRule called DropwizardAppRule, which is used for integration tests. You use it like this:
#ClassRule
public static final DropWizardAppRule<MyConfiguration> APP_RULE = new DropwizardAppRule(MyApplication.class, myYmlResourceFilePath, ConfigOverride("mydatabase.url", myJdbcUrl));
It will start up your application, configuring it with your yml resource file, with overrides that you specified in the constructor. Note, however, that your overrides are bound at construction time.
There are also JUnit rules out there to start up a Docker container, and I'm using one to start up MySql, and a JUnit RuleChain to enforce the fact that the container must start up before I launch my Dropwizard application that depends on it.
All that works great, if I'm willing to specify in advance what port I want the MySql container to expose. I'm not. I want these integration tests to run on a build machine, quite possibly in parallel for branch builds of the same project, and I would strongly prefer to use the mechanism where you ask Docker to pick any available port, and use that.
The problem I run into with that, is that the exposed container port is not known at the time that the DropwizardAppRule is constructed, which is the only time you can bind configuration overrides.
The solution I adopted was to make a wrapper JUnit Rule, like so:
public class CreateWhenRunRuleWrapper<T extends ExternalResource> extends ExternalResource {
private final Supplier<T> wrappedRuleFactory;
private T wrappedRule;
public CreateWhenRunRuleWrapper(Supplier<T> wrappedRuleFactory) {
this.wrappedRuleFactory = wrappedRuleFactory;
}
public T getWrappedRule() {
return wrappedRule;
}
#Override
protected void before() throws Throwable {
wrappedRule = wrappedRuleFactory.get();
wrappedRule.before();
}
#Override
protected void after() {
wrappedRule.after();
}
}
This works, allowing me to construct the DropWizardAppRule class in the before() method, but is quite obviously outside JUnit's design intent, as shown by the fact that I had to locate it in the org.junit.rules package, in order to empower my class to be able to call the before() and after() methods of the late-created Rule.
What would be a more orderly, best practice way to accomplish the same objective?
2 Options we came up with:
The hacky solution is to use static {} which executes the code after spinning up the container but before initialising the dropwizard instance:
public static final GenericContainer mongodb = new GenericContainer("mongo:latest").withExposedPorts(27017);
static {
mongodb.start();
System.setProperty("dw.mongoConfig.uri", "mongodb://" + mongodb.getContainerIpAddress() + ":" + mongodb.getMappedPort(27017));
}
#ClassRule
public static final DropwizardIntegrationAppRule<Config> app1 = new DropwizardIntegrationAppRule<>(Service.class);
The second option is cleaner and much like yours.
private static final MongoDContainerRule mongo = new MongoDContainerRule();
private static final DropwizardIntegrationAppRule<Config> app = new DropwizardIntegrationAppRule<>(Service.class);
#ClassRule
public static final RuleChain chain = RuleChain
.outerRule(mongo)
.around(app)
MongoDContainerRule is like your wrapper but it also sets the right port through system properties.
public class MongoDContainerRule extends MongoDBContainerBase {
private static final GenericContainer mongodb = new GenericContainer("mongo:latest").withExposedPorts(27017);
#Override
protected void before() throws Throwable {
mongodb.start();
System.setProperty("dw.mongoConfig.uri", "mongodb://" + mongodb.getContainerIpAddress() + ":" + mongodb.getMappedPort(27017));
System.setProperty("dw.mongoConfig.tls", "false");
System.setProperty("dw.mongoConfig.dbName", DB_NAME);
}
#Override
protected void after() {
mongodb.stop();
}
}
The container will expose mongodb on a free port. mongodb.getMappedPort(internalPort) will return it. System.setProperty("dw.*") injects values into the dropwizard config.
I'm learning about the design patterns and I encountered a problem which I cant resolve. I'm writing a client/server script. The administrator client send a task with its task data in json format, and the server should instantiate an object accordingly to the recieved task type, and fill its constructor with correct classes. As you can see bellow there are two example class.
public class StartProcessing implements ITask{
private final IProcessor dataProcessor;
public StartProcessing(IProcessor dataProcessor){
this.dataProcessor = dataProcessor;
}
#Override
public void ProcessTask() {
this.dataProcessor.StartProcess();
}
}
public class StartQueueFiller implements ITask{
private IQueueFiller queueFiller;
public StartQueueFiller(IQueueFiller queueFiller){
this.queueFiller = queueFiller;
}
#Override
public void ProcessTask() {
this.queueFiller.Start();
}
}
interface ITask {
public void ProcessTask();
}
I've tried something like this, but I'll have like 50 different process and hundreds of tasks, so the constructor will be unmanageable, and I think the factory pattern is not so good in this case, and probably I just miss the point of the pattern. So how you would solve this problem? What should I use instead of the factory pattern?
public class TaskFactory(){
private final IProcessor processor;
private final IQueueFiller queuefiller;
public TaskFactory(IProcessor processor, IQueueFiller queuefiller){
this.processor = processor;
this.queuefiller = queuefiller;
}
public ITask Create(String task){
switch(task){
case "startprocessor":
return new StartProcessing(this.processor);
case "startqueuefiller":
return new StartQueueFiller(this.queuefiller);
}
}
}
I would just use the Abstract Factory pattern:
public interface TaskFactory {
Task create();
}
Then we can store a bunch of factories in a data structure of some kind, e.g.:
private final Map<String, TaskFactory> factoriesMap = new HashMap<>();
void registerFactory(String identifier, TaskFactory factory) {
factoriesMap.put(identifier, factory);
}
public Task create(String identifier) {
return factoriesMap.get(identifier).create();
}
Then we can register different kinds of factories using a lambda or something:
Processor processor = ...;
registerFactory("startprocessor", () -> new StartProcessingTask(processor));
etc.
At some point you're going to realize that your "factory map" is basically a kind of Service Locator, in which case you either need to double-down on that, or find an alternative solution. I tend to prefer Dependency Injection as an approach here. Depending on your DI environment, you might make all your TaskFactory instances injectable using qualifiers. You can either bind lazy providers of actual task objects, or bind a factory-like object (e.g. "assisted inject").
I'm currently using a pool connection(Hikari) and an abstract factory pattern to implement my MySQL queries in Java like this:
MySqlFactoryDAO.java
public class MySqlFactoryDAO extends FactoryDAO {
private static HikariDataSource connPool_;
public static Connection createConnection() throws SQLException {
if (connPool_ == null) {
// Load database configuration
PropertiesFile props = FactoryConfig.getConfig().getDatabaseProperties();
connPool_ = new HikariDataSource();
connPool_.setJdbcUrl(props.getString(Params.DB_URL,""));
connPool_.setUsername(props.getString(Params.DB_USER,"root"));
connPool_.setPassword(props.getString(Params.DB_PASSWORD,"root"));
}
return connPool_.getConnection();
}
//-------------------------------------------------------------------------
public ProductDAO getProductDAO() {
return new ProductMySQLFactoryDAO();
}
}
ProductMySQLFactoryDAO.java
public class ProductMySQLFactoryDAO implements ProductDAO {
public int insertProduct(String name) {
...
Connection conn = MySqlFactoryDAO.createConnection();
...
}
}
I was wondering if this code is thread safe and I think that there is a problem at the time of initialization of coonPool_. I have read things like "Initialization-on-demand_holder_idiom" in wikipedia but I am not sure about it. Does anyone have a better implementation of this to solve this problem or just a better new one?
No, it's not thread-safe. Two threads might call createConnection() concurrently, both see the pool as null, and both create a new DataSource.
The method needs to be synchronized. Or the pool must be created at class initializing time:
private static final HikariDataSource DATA_SOURCE = createDataSource();
Your connPool_ field should be private, too.
I got a class Config wich looks like that:
public Class Config {
public static int someIntValue = 0;
public static String someText = "some text";
}
What i want to do now is saving and loading that config and there is also that inital config if there is no need to load another. So the config can change at any point in the programm.
What i came up with was a Singelton like pattern
public Class Config {
public static Config instance;
private int someIntValue = 0;
private int String someText = "some text";
public static Config getInstance(){
if(instance == null)
instance = new Config();
return instance;
}
public void setInstance(Config config){
this.instance = config;
}
//getter/setter
...
}
But in the end it doesnt look like the best approach and im not quite happy with it :/
Maybe you guys can help me out with a usual / "best practice" way to do that.
Best Regards
Made
I would just use java.util.Properties, or some wrapper around it. Another good approach is java bean and something like xstream to save/load stuff.
Usually in Java for configuration use properties files. And then use ResuorseBundle for reading properties.
Your "singleton" is not a Singleton in the conventional sense.
1) Field instance must be private
2) Remove SetInstance method
3) And you should make your singleton thread safe.
If you'd consider avoiding writing the boilerplate code around java.util.Properties, you can have a look at something that does it for you: OWNER API.
It's configurable to tailor your needs and it offers some additional neat features if compared to java.util.Properties (read the docs).
Example. You define an interface with your configuration parameters:
public interface ServerConfig extends Config {
int port();
String hostname();
#DefaultValue("42")
int maxThreads();
#DefaultValue("1.0")
String version();
}
Then you use it like this:
public class MyApp {
private static ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
private MainWindow window;
public MyApp() {
// you can pass the cfg object as dependency, example:
window = new MainWindow(cfg);
}
public void start() {
window.show();
}
public static void main(String[] args) {
// you can use it directly, example:
System.out.println("MyApp version " + cfg.version() + " copyright (c) ACME corp.");
MyApp app = new MyApp();
app.start();
}
}
You can define the cfg object as member instance on the classes where you need, or you can pass the instance to constructors and methods where you need it.
Version 1.0.4 will be released soon and it will include also "hot reload" and many improvements.