I am using Java EE 6 and need to load configuration from a ".properties" file. Is there a recommended way (best practice) to load the values from the configuration file using dependency injection? I found annotations for this in Spring, but I have not found a "standard" annotation for Java EE.
This guy have developed a solution from scratch:
http://weblogs.java.net/blog/jjviana/archive/2010/05/18/applicaction-configuration-java-ee-6-using-cdi-simple-example
"I couldn't find a simple example of how to configure your application
with CDI by reading configuration attributes from a file..."
But I wonder if there is a more standard way instead of creating a configuration factory...
Configuration annotation
package com.ubiteck.cdi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.enterprise.util.Nonbinding;
import javax.inject.Qualifier;
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
public #interface InjectedConfiguration {
/**
* Bundle key
* #return a valid bundle key or ""
*/
#Nonbinding String key() default "";
/**
* Is it a mandatory property
* #return true if mandator
*/
#Nonbinding boolean mandatory() default false;
/**
* Default value if not provided
* #return default value or ""
*/
#Nonbinding String defaultValue() default "";
}
The configuration factory could look like :
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
public class ConfigurationInjectionManager {
static final String INVALID_KEY="Invalid key '{0}'";
static final String MANDATORY_PARAM_MISSING = "No definition found for a mandatory configuration parameter : '{0}'";
private final String BUNDLE_FILE_NAME = "configuration";
private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_FILE_NAME);
#Produces
#InjectedConfiguration
public String injectConfiguration(InjectionPoint ip) throws IllegalStateException {
InjectedConfiguration param = ip.getAnnotated().getAnnotation(InjectedConfiguration.class);
if (param.key() == null || param.key().length() == 0) {
return param.defaultValue();
}
String value;
try {
value = bundle.getString(param.key());
if (value == null || value.trim().length() == 0) {
if (param.mandatory())
throw new IllegalStateException(MessageFormat.format(MANDATORY_PARAM_MISSING, new Object[]{param.key()}));
else
return param.defaultValue();
}
return value;
} catch (MissingResourceException e) {
if (param.mandatory()) throw new IllegalStateException(MessageFormat.format(MANDATORY_PARAM_MISSING, new Object[]{param.key()}));
return MessageFormat.format(INVALID_KEY, new Object[]{param.key()});
}
}
Tutorial with explanation and Arquillian test
Even though it does not exactly cover your question, this part of the Weld documentation might be of interest for you.
Having mentioned this - no, there is no standard way to inject arbitrary resources / resource files. I guess it's simply beyond the scope of a spec to standardise such highly custom-dependent requirement (Spring is no specification, they can simply implement whatever they like). However, what CDI provides is a strong (aka typesafe) mechanism to inject configuration-holding beans on one side, and a flexible producer mechanism to read and create such beans on the other side. Definitely this is the recommended way you were asking about.
The approach you are linking to is certainly a pretty good one - even though it might me too much for your needs, depending on the kind of properties you are planning to inject.
A very CDI-ish way of continuing would be to develop a CDI extension (that would nicely encapsulate all required classes) and deploy it independently with your projects. Of course you can also contribute to the CDI-extension catalog or even Apache Deltaspike.
See #ConfigProperty of Apache DeltaSpike
The only "standard" way of doing this would be to use a qualifier with a nonbinding annotation member, and make sure all of your injections are dependent scoped. Then in your producer you can get a hold of the InjectionPoint and get the key off the qualifier in the injection point. You'd want something like this:
#Qualifier
public #interface Property {
#Nonbinding String value default "";
}
...
#Inject #Property("myKey") String myKey;
...
#Produces #Property public String getPropertyByKey(InjectionPoint ip) {
Set<Annotation> qualifiers = ip.getQualifiers
// Loop through qualifers looking for Property.class save that off
return ResourceBundle.getBundle(...).getString(property.key);
}
There are obviously some enhancements you can do to that code, but it should be enough to get you started down the right track.
Related
This question has two parts:
By default, what URL protocols are considered valid for specifying resources to Cypher's LOAD CSV command?
So far, I've successfully loaded CSV files into Neo4j using http and file protocols. A comment on this unrelated question indicates that ftp works as well, but I haven't had tried this because I have no use case.
What practical options do I have to configure non-standard URI protocols? I'm running up against a Neo.TransientError.Statement.ExternalResourceFailure: with "Invalid URL specified (unknown protocol)". Other than digging into the Neo4j source, is there anyway to modify this validation/setting, provided that the host machine is capable of resolving the resource with the specified protocol?
Neo4j relies on the capabilities of the JVM. According to https://docs.oracle.com/javase/7/docs/api/java/net/URL.html the default protocols are:
http, https, ftp, file, jar
Please note that file URLs are interpreted from the server's point of view and not from the client side (a common source of confusion).
To use custom URLs you need to understand how the JVM deals with those. The javadocs for URL class explain an approach by using a system property to provide custom URL handlers. It should be good enough to provide this system property in neo4j-wrapper.conf and drop the jar file containing your handler classes into the plugins folder. (Note: I did not validate that approach myself, but I'm pretty confident that it will work).
Here is a complete example, using the technique of implementing your own URLStreamHandler to handle the resource protocol. You must name your class 'Handler', and the last segment of the package name must be the protocol name (in this case, resource)
src/main/java/com/example/protocols/resource/Handler.java:
package com.example.protocols.resource;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
public class Handler extends URLStreamHandler {
private final ClassLoader classLoader;
public Handler() {
this.classLoader = getClass().getClassLoader();
}
#Override
protected URLConnection openConnection(URL url) throws IOException {
URL resource = classLoader.getResource(url.getPath());
if (resource == null) {
throw new FileNotFoundException("Resource file not found: " + url.getPath());
}
return resource.openConnection();
}
}
From here, we need to set the system property java.protocol.handler.pkgs to include the base package com.example.protocols so that the protocol is registered. This can be done statically in a Neo4j ExtensionFactory. Since the class gets loaded by Neo4j, we know that the static block will be executed. We also need to provide our own URLAccessRule, since Neo4j by default only allows use of a few select protocols. This can also happen in the ExtensionFactory.
src/main/java/com/example/protocols/ProtocolInitializerFactory.java:
package com.example.protocols;
import org.neo4j.annotations.service.ServiceProvider;
import org.neo4j.graphdb.security.URLAccessRule;
import org.neo4j.kernel.extension.ExtensionFactory;
import org.neo4j.kernel.extension.ExtensionType;
import org.neo4j.kernel.extension.context.ExtensionContext;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
#ServiceProvider
public class ProtocolInitializerFactory extends ExtensionFactory<ProtocolInitializerFactory.Dependencies> {
private static final String PROTOCOL_HANDLER_PACKAGES = "java.protocol.handler.pkgs";
private static final String PROTOCOL_PACKAGE = ProtocolInitializerFactory.class.getPackageName();
static {
String currentValue = System.getProperty(PROTOCOL_HANDLER_PACKAGES, "");
if (currentValue.isEmpty()) {
System.setProperty(PROTOCOL_HANDLER_PACKAGES, PROTOCOL_PACKAGE);
} else if (!currentValue.contains(PROTOCOL_PACKAGE)) {
System.setProperty(PROTOCOL_HANDLER_PACKAGES, currentValue + "|" + PROTOCOL_PACKAGE);
}
}
public interface Dependencies {
URLAccessRule urlAccessRule();
}
public ProtocolInitializerFactory() {
super(ExtensionType.DATABASE, "ProtocolInitializer");
}
#Override
public Lifecycle newInstance(ExtensionContext context, Dependencies dependencies) {
URLAccessRule urlAccessRule = dependencies.urlAccessRule();
return LifecycleAdapter.onInit(() -> {
URLAccessRule customRule = (config, url) -> {
if ("resource".equals(url.getProtocol())) { // Check the protocol name
return url; // Optionally, you can validate the URL here and throw an exception if it is not valid or should not be allowed access
}
return urlAccessRule.validate(config, url);
};
context.dependencySatisfier().satisfyDependency(customRule);
});
}
}
After setting this up, follow the guide to packaging these classes as a Neo4j plugin and drop it into your database's plugins directory.
Admittedly, needing to override the default URLAccessRule feels a little bit shady. It may be better to simply implement the URLStreamHandler, and use another CSV loading method like APOC's apoc.load.csv. This will not require overriding the URLAccessRule, but it will require setting the Java system property java.protocol.handler.pkgs.
Suppose I have two sets of controllers in Spring:
/jsonapi1/*
/jsonapi2/*
both of which return objects that are to be interpretted as JSON text.
I'd like some kind of filter to wrap the responses from one set of these controllers so that:
the original response is contained within another object.
For example, if /jsonapi1/count returns:
{"num_humans":123, "num_androids":456}
then the response should be wrapped and returned as follows:
{ "status":0,
"content":{"num_humans":123, "num_androids":456}
}
if an exception happens in the controller, then filter should catch the exception and report it as follows
{ "status":5,
"content":"Something terrible happened"
}
The responses from the other controllers are returned unchanged.
We're currently customizing a MappingJackson2HttpMessageConverter passed to WebMvcConfigurerAdapter.configureMessageConverters in order to perform the above tasks. Works great except that it doesn't seem possible for this approach to be selective about the URLs (or controller classes) it applies to.
Is it possible to apply these kinds of wrappers to individual controller classes or URLs?
Update: Servlet filters look like a solution. Is it possible chose which filter gets applied to which controller methods, or which URLs?
I was struggling on this for multiple days. The solution by #Misha didn't work for me. I was able to finally get this working using ControllerAdvice and ResponseBodyAdvice.
ResponseBodyAdvice allows to inject custom transformation logic on the response returned by a controller but before it is converted to HttpResponse and committed.
This is how my controller method looks:
#RequestMapping("/global/hallOfFame")
public List<HallOfFame> getAllHallOfFame() {
return hallOfFameService.getAllHallOfFame();
}
Now i wanted to add some standard fields around the response like devmessage and usermessage. That logic goes into the ResponseAdvice:
#ControllerAdvice
public class TLResponseAdvice implements ResponseBodyAdvice<Object> {
#Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
#Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
// TODO Auto-generated method stub
final RestResponse<Object> output = new RestResponse<>();
output.setData(body);
output.setDevMessage("ResponseAdviceDevMessage");
output.setHttpcode(200);
output.setStatus("Success");
output.setUserMessage("ResponseAdviceUserMessage");
return output;
}
}
The entity classes look like this:
#Setter // All lombok annotations
#Getter
#ToString
public class RestResponse<T> {
private String status;
private int httpcode;
private String devMessage;
private String userMessage;
private T data;
}
#Entity
#Data // Lombok
public class HallOfFame {
#Id
private String id;
private String name;
}
To handle exceptions, simply create another ControllerAdvice with ExceptionHandler. Use the example in this link.
Advantages of this solution:
It keeps your controllers clean. You can support any return type from your controller methods.
Your controller return type class does not need to extend some base class as required by the AOP approach.
You do not need to hack your way through Spring filters by using HttpServletResponseWrappers. They come up with a performance penalty.
EDIT - 17th September 2019
To handle exceptions use #ExceptionHandler. Refer code below.
#ExceptionHandler(Exception.class)
#ResponseBody
public MyResponseEntity<Object> handleControllerException(HttpServletRequest request, Throwable ex) {
// default value
int httpCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
if(ex instanceof ResourceNotFoundException) {
httpCode = HttpStatus.NOT_FOUND.value();
}
...
}
The way I understand your question, you have exactly three choices.
Option #1
Manually wrap your objects in simple SuccessResponse, ErrorResponse, SomethingSortOfWrongResponse, etc. objects that have the fields you require. At this point, you have per-request flexibility, changing the fields on one of the response wrappers is trivial, and the only true drawback is code repetition if many of the controller's request methods can and should be grouped together.
Option #2
As you mentioned, and filter could be designed to do the dirty work, but be wary that Spring filters will NOT give you access to request or response data. Here's an example of what it might look like:
#Component
public class ResponseWrappingFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) {
// Perform the rest of the chain, populating the response.
chain.doFilter(request, response);
// No way to read the body from the response here. getBody() doesn't exist.
response.setBody(new ResponseWrapper(response.getStatus(), response.getBody());
}
}
If you find a way to set the body in that filter, then yes, you could easily wrap it up. Otherwise, this option is a dead end.
Option #3
A-ha. So you got this far. Code duplication is not an option, but you insist on wrapping responses from your controller methods. I'd like to introduce the true solution - aspect-oriented programming (AOP), which Spring supports fondly.
If you're not familiar with AOP, the premise is as follows: you define an expression that matches (like a regular expression matches) points in the code. These points are called join points, while the expressions that match them are called pointcuts. You can then opt to execute additional, arbitrary code, called advice, when any pointcut or combination of pointcuts are matched. An object that defines pointcuts and advice is called an aspect.
It's great for expressing yourself more fluently in Java. The only drawback is weaker static type checking. Without further ado, here's your response-wrapping in aspect-oriented programming:
#Aspect
#Component
public class ResponseWrappingAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void anyControllerPointcut() {}
#Pointcut("execution(* *(..))")
public void anyMethodPointcut() {}
#AfterReturning(
value = "anyControllerPointcut() && anyMethodPointcut()",
returning = "response")
public Object wrapResponse(Object response) {
// Do whatever logic needs to be done to wrap it correctly.
return new ResponseWrapper(response);
}
#AfterThrowing(
value = "anyControllerPointcut() && anyMethodPointcut()",
throwing = "cause")
public Object wrapException(Exception cause) {
// Do whatever logic needs to be done to wrap it correctly.
return new ErrorResponseWrapper(cause);
}
}
The final result will be the non-repeating response wrapping that you seek. If you only want some or one controller receive this effect, then update the pointcut to match methods only within instances of that controller (rather than any class holding the #Controller annotation).
You'll need to include some AOP dependencies, add the AOP-enabling annotation in a configuration class, and make sure something component-scans the package this class is in.
Simplest way i manage custom responses from controllers is by utilising the Map variable.
so your code ends up looking like:
public #ResponseBody Map controllerName(...) {
Map mapA = new HashMap();
mapA.put("status", "5");
mapA.put("content", "something went south");
return mapA;
}
beauty of is is that you can configure it any thousand ways.
Currently i use for object transmition, custom exception handling and data reporting, too easy.
Hope this helps
I am also using AOP with #Around. Developed a custom annotation and using that for point cut. I am using a global Response. It has the status, Message and data which is of type List of type
List <? extends parent> dataList
( which can solve your class cast exception). All the entities extends this Parent class. This way I can set all the data into my List.
Also I am using the message key as param with the custom annotation and setting it in action.
Hope this helps.
I'm currently working with Symfony2 and Doctrine2, but I must override the Doctrine2 EntityManager and add it some "undelete" features (ACLs inside).
So I'm wondering : is there a way to override the EntityManager class and specify Doctrine2 in Symfony2 to use it as implementation of the EntityManager?
Thank you for any help!
After Doctrine 2.4 (Doctrine 2.4 release) you need to use decorator for this. Do not extend EntityManager directly.
First you need to implement you own entity manager decorator that extends Doctrine\ORM\Decorator\EntityManagerDecorator (like #Dana)
But you can't just change doctrine.orm.entity_manager.class to your new decorator because EntityManagerDecorator requires EntityManagerInterface in it's constructor:
public function __construct(EntityManagerInterface $wrapped)
You can't just pass doctrine.orm.entity_manager as a parameter here because it will be a recursion.
And don't do like this:
return new self(\Doctrine\ORM\EntityManager::create(
What you need is to configure your decorator in services like a decorator:
yourcompany_entity_manager:
public: false
class: YourCompany\ORM\EntityManagerDecorator
decorates: doctrine.orm.default_entity_manager
arguments: ["#yourcompany_entity_manager.inner"]
Now you'll have your decorator as a default entity manager for Doctrine. #yourcompany_entity_manager.inner is actually a link to doctrine.orm.default_entity_manager that will be passed to yourcompany_entity_manager constructor.
Symfony docs for configuring decorators: link
Btw this command is very useful to debug your services:
app/console container:debug | grep entity_manager
Yes, it's possible with two steps:
1 - Override the doctrine.orm.entity_manager.class parameter to point to your custom entity manager (which should extend Doctrine\ORM\EntityManager.)
2 - Your custom entity manager must override the create method so that it returns an instance of your class. See my example below, and note the last line regarding MyEntityManager:
public static function create($conn, Configuration $config, EventManager $eventManager = null) {
if (!$config->getMetadataDriverImpl()) {
throw ORMException::missingMappingDriverImpl();
}
if (is_array($conn)) {
$conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ? : new EventManager()));
} else if ($conn instanceof Connection) {
if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
throw ORMException::mismatchedEventManager();
}
} else {
throw new \InvalidArgumentException("Invalid argument: " . $conn);
}
// This is where you return an instance of your custom class!
return new MyEntityManager($conn, $config, $conn->getEventManager());
}
You'll also need to use the following in your class:
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\ORMException;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
To be honest, I'm surprised that the 2nd step is required at all, I would think this should be possible to accomplish using only the service container.
At least in Doctrine/ORM 2.4, the doc string of the EntityManager class explicitly discourages inheriting from Doctrine\ORM\EntityManager, instead they suggest inheriting from Doctrine\ORM\Decorator\EntityManagerDecorator:
/**
* The EntityManager is the central access point to ORM functionality.
* ...
* You should never attempt to inherit from the EntityManager: Inheritance
* is not a valid extension point for the EntityManager. Instead you
* should take a look at the {#see \Doctrine\ORM\Decorator\EntityManagerDecorator}
* and wrap your entity manager in a decorator.
* ...
*/
/* final */class EntityManager implements EntityManagerInterface
{
...
So, extend EntityManagerDecorator and make whatever changes you need. You will need to implement the create() factory method, but you don't need to copy EntityManager's implementation now:
use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\Common\EventManager;
use Doctrine\ORM\Configuration;
class MyEntityManager extends EntityManagerDecorator
{
/**
* {#inheritDoc}
*/
public function persist($entity)
{
// do something interesting
parent::persist($entity);
}
public function create($conn, Configuration $config, EventManager $eventManager = null)
{
return new self(\Doctrine\ORM\EntityManager::create($conn, $config, $eventManager));
}
}
Then override the doctrine.orm.entity_manager.class parameter to point to your custom entity manager class.
The docs don't cover everything, in many cases you just have to read the code.
I found the process of extending the entity manager extremely counterintuitive,
despite a decent grasp of concepts including dependency injection, service locator, code generation, caching and the decorator pattern.
Hopefully this concise example will paint a clear picture for you (this expands on the answer by #user2563451)
Symfony Version (Mon Aug 20 13:05:58 CEST 2018)
$ composer info | grep -E -e symfony/framework -e 'doctrine/(common|orm|dbal)'
doctrine/common v2.9.0 Common Library for Doctrine projects
doctrine/dbal v2.8.0 Database Abstraction Layer
doctrine/orm v2.6.2 Object-Relational-Mapper for PHP
symfony/framework-bundle v4.1.3 Symfony FrameworkBundle
config/services.yaml
App\Doctrine\ORM\CustomEntityManager:
public: false # optional afaik
decorates: doctrine.orm.original_entity_manager
arguments: [ '#App\Doctrine\ORM\CustomEntityManager.inner' ]
config/packages/doctrine.yaml
doctrine:
orm:
auto_generate_proxy_classes: '%kernel.debug%'
default_entity_manager: original
entity_managers:
original:
connection: from_env
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: false
mappings:
TimeTracking:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/php/Model'
prefix: TimeTracking\Model
alias: TimeTracking
mapping: true
#mapper_number_5:
# (...)
src/php/App/Doctrine/ORM/CustomEntityManager.php
<?php
namespace App\Doctrine\ORM;
use App\Doctrine\ORM\Proxy\SoggyProxyFactory;
use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\Proxy\ProxyFactory;
/**
* Writes custom proxy-class methods with support for the set-or-get-trait
* #property ProxyFactory soggyProxyFactory
*/
class CustomEntityManager extends EntityManagerDecorator
{
/// SUPER: __construct(EntityManagerInterface $wrapped) { $this->wrapped = $wrapped; }
private $soggyProxyFactory;
public function getProxyFactory() {
$config = $this->getConfiguration();
if (null === $this->soggyProxyFactory) {
$this->soggyProxyFactory = new SoggyProxyFactory(
$this,
$config->getProxyDir(),
$config->getProxyNamespace(),
$config->getAutoGenerateProxyClasses()
);
}
return $this->soggyProxyFactory;
}
}
references
http://symfony.com/doc/current/service_container/service_decoration.html
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
I have successfully set up a quick test of creating a "REST-like" service that returns an object serialized to JSON, and that was quite easy and quick (based on this article).
But while returning JSON-ified objects was easy as peach, I have yet to see any examples dealing with input parameters that are not primitives. How can I pass in a complex object as an argument? I am using Apache CXF, but examples using other frameworks like Jackson are welcome too :)
Client side would probably be something like building a javascript object, pass it into JSON.stringify(complexObj), and pass that string as one of the parameters.
The service would probably look something like this
#Service("myService")
class RestService {
#GET
#Produces("application/json")
#Path("/fooBar")
public Result fooBar(#QueryParam("foo") double foo, #QueryParam("bar") double bar,
#QueryParam("object") MyComplex object) throws WebServiceException {
...
}
}
Sending serialized objects as parameters would probably quickly touch the 2KB URL-limit imposed by Internet Explorer. Would you recommend using POST in these cases, and would I need to change much in the function definitions?
After digging a bit I quickly found out there are basically two options:
Option 1
You pass a "wrapper object" containing all the other parameters to the service. You might need to annotate this wrapper class with JAXB annotations like #XmlRootElement in order for this to work with the Jettison based provider, but if you use Jackson in stead there is no need. Just set the content type to the right type and the right message body reader will be invoked.
This will only work for POST type services of course (AFAIK).
Example
This is just an example of turning the service mentioned in the original question into one using a wrapper object.
#Service("myService")
class RestService {
#POST
#Produces("application/json")
#Path("/fooBar")
public Result fooBar(
/**
* Using "" will inject all form params directly into a ParamsWrapper
* #see http://cxf.apache.org/docs/jax-rs-basics.html
*/
#FormParam("") FooBarParamsWrapper wrapper
) throws WebServiceException {
doSomething(wrapper.foo);
}
}
class ParamsWrapper {
double foo, bar;
MyComplexObject object;
}
Option 2
You can provide some special string format that you pack your objects into and then implement either a constructor taking a string, a static valueOf(String s) or a static fromString(String s) in the class that will take this string and create an object from it. Or quite similar, create a ParameterHandler that does exactly the same.
AFAIK, only the second version will allow you to call your services from a browser using JSONP (since JSONP is a trick restricted to GET). I chose this route to be able to pass arrays of complex objects in the URI.
As an example of how this works, take the following domain class and service
Example
#GET
#Path("myService")
public void myService(#QueryParam("a") MyClass [] myVals) {
//do something
}
class MyClass {
public int foo;
public int bar;
/** Deserializes an Object of class MyClass from its JSON representation */
public static MyClass fromString(String jsonRepresentation) {
ObjectMapper mapper = new ObjectMapper(); //Jackson's JSON marshaller
MyClass o= null;
try {
o = mapper.readValue(jsonRepresentation, MyClass.class );
} catch (IOException e) {
throw new WebApplicationException()
}
return o;
}
}
A URI http://my-server.com/myService?a={"foo":1, "bar":2}&a={"foo":100, "bar":200} would in this case be deserialized into an array composed of two MyClass objects.
2019 comment:
Seeing that this answer still gets some hits in 2019, I feel I should comment. In hindsight, I would not recomment option 2, as going through these steps just to be able to be able to do GET calls adds complexity that's probably not worth it. If your service takes such complex input, you will probably not be able to utilize client side caching anyway, due to the number of permutations of your input. I'd just go for configuring proper Cross-Origin-Sharing (CORS) headers on the server and POST the input. Then focus on caching whatever you can on the server.
The accepted answer is missing #BeanParam. See
https://docs.jboss.org/resteasy/docs/3.0-rc-1/javadocs/javax/ws/rs/BeanParam.html
for further details. It allows you to define query params inside a wrapper object.
E.g.
public class TestPOJO {
#QueryParam("someQueryParam")
private boolean someQueryParam;
public boolean isSomeQueryParam() {
return someQueryParam;
}
public boolean setSomeQueryParam(boolean value) {
this.someQueryParam = value;
}
}
... // inside the Resource class
#GET
#Path("test")
public Response getTest(#BeanParam TestPOJO testPOJO) {
...
}
the best and simplest solution is to send your object as a json string and in server side implement a method which will decode that json and map to the specified object as per your need.. and yes it`s better to use POST.
A database application that I'm currently working on, stores all sorts of settings in the database. Most of those settings are there to customize certain business rules, but there's also some other stuff in there.
The app contains objects that specifically do a certain task, e.g., a certain complicated calculation. Those non-UI objects are unit-tested, but also need access to lots of those global settings. The way we've implemented this right now, is by giving the objects properties that are filled by the Application Controller at runtime. When testing, we create the objects in the test and fill in values for testing (not from the database).
This works better, in any case much better than having all those objects need some global Settings object --- that of course effectively makes unit testing impossible :) Disadvantage can be that you sometimes need to set a dozen of properties, or that you need to let those properties 'percolate' into sub-objects.
So the general question is: how do you provide access to global application settings in your projects, without the need for global variables, while still being able to unit test your code? This must be a problem that's been solved 100's of times...
(Note: I'm not too much of an experienced programmer, as you'll have noticed; but I love to learn! And of course, I've already done research into this topic, but I'm really looking for some first-hand experiences)
You could use Martin Fowlers ServiceLocator pattern. In php it could look like this:
class ServiceLocator {
private static $soleInstance;
private $globalSettings;
public static function load($locator) {
self::$soleInstance = $locator;
}
public static function globalSettings() {
if (!isset(self::$soleInstance->globalSettings)) {
self::$soleInstance->setGlobalSettings(new GlobalSettings());
}
return self::$soleInstance->globalSettings;
}
}
Your production code then initializes the service locator like this:
ServiceLocator::load(new ServiceLocator());
In your test-code, you insert your mock-settings like this:
ServiceLocator s = new ServiceLocator();
s->setGlobalSettings(new MockGlobalSettings());
ServiceLocator::load(s);
It's a repository for singletons that can be exchanged for testing purposes.
I like to model my configuration access off of the Service Locator pattern. This gives me a single point to get any configuration value that I need and by putting it outside the application in a separate library, it allows reuse and testability. Here is some sample code, I am not sure what language you are using, but I wrote it in C#.
First I create a generic class that will models my ConfigurationItem.
public class ConfigurationItem<T>
{
private T item;
public ConfigurationItem(T item)
{
this.item = item;
}
public T GetValue()
{
return item;
}
}
Then I create a class that exposes public static readonly variables for the configuration item. Here I am just reading the ConnectionStringSettings from a config file, which is just xml. Of course for more items, you can read the values from any source.
public class ConfigurationItems
{
public static ConfigurationItem<ConnectionStringSettings> ConnectionSettings = new ConfigurationItem<ConnectionStringSettings>(RetrieveConnectionString());
private static ConnectionStringSettings RetrieveConnectionString()
{
// In .Net, we store our connection string in the application/web config file.
// We can access those values through the ConfigurationManager class.
return ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["ConnectionKey"]];
}
}
Then when I need a ConfigurationItem for use, I call it like this:
ConfigurationItems.ConnectionSettings.GetValue();
And it will return me a type safe value, which I can then cache or do whatever I want with.
Here's a sample test:
[TestFixture]
public class ConfigurationItemsTest
{
[Test]
public void ShouldBeAbleToAccessConnectionStringSettings()
{
ConnectionStringSettings item = ConfigurationItems.ConnectionSettings.GetValue();
Assert.IsNotNull(item);
}
}
Hope this helps.
Usually this is handled by an ini file or XML configuration file. Then you just have a class that reads the setting when neeed.
.NET has this built in with the ConfigurationManager classes, but it's quite easy to implement, just read text files, or load XML into DOM or parse them by hand in code.
Having config files in the database is ok, but it does tie you to the database, and creates an extra dependancy for your app that ini/xml files solve.
I did this:
public class MySettings
{
public static double Setting1
{ get { return SettingsCache.Instance.GetDouble("Setting1"); } }
public static string Setting2
{ get { return SettingsCache.Instance.GetString("Setting2"); } }
}
I put this in a separate infrastructure module to remove any issues with circular dependencies.
Doing this I am not tied to any specific configuration method, and have no strings running havoc in my applications code.