I'm writing some utlility methods that helps constructing complex object structures for webservice requests.
When using Spring: is it better to provide these classes as static utilities or inject/autowire them?
Example:
//the service used to build different parts for the webservice request
class RequestService {
public addCurrency(Req req) {
//create currency xml object
req.addCurrency(cur);
}
public addPassengers(Req req, List<String> names) {
for (String name : names) {
req.getPassengers().add(passenger);
//create passengers
}
}
}
class WebserviceClient {
void runWithStatic() {
Req req = new Req();
RequestService.addCurrency(req, ..);
RequestService.addPassengers(req, ..);
send(req);
}
//or
#Autowired
private RequestService reqService;
void runWithInjected() {
Req req = new Req();
reqService.addCurrency(req, ..);
reqService.addPassengers(req, ..);
send(req);
}
}
Is there one approach one would prefer from the overal spring design point of view?
Related
We need to call a Bean class using spring remoting and also set dynamic header in the call. We can set custom HttpInvokerRequestExecutor in the HttpInvokerProxyFactoryBean and add header but how to set dynamic header generated on the fly for the request?
In the Config class, declaring the HttpInvokerProxyFactoryBean
#Bean
#Qualifier("service")
public HttpInvokerProxyFactoryBean invoker() {
HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean();
invoker.setServiceUrl(url);
invoker.setServiceInterface(Service.class);
return invoker;
}
In the invoker class
#Autowired
Service service;
public void invoke(Bean bean) {
service.process(bean);
}
Its been a long time that I used spring remoting but as far as I remember I found a solution to this by subclassing of SimpleHttpInvokerRequestExecutor which is default when you do not set any custom request executor to HttpInvokerProxyFactoryBean.
IMHO you can write a custom request executor which you can set custom header values and a simple helper component which sets the dynamically provided values to the executor before the next request.
CustomHttpInvokerRequestExecutor:
public class CustomHttpInvokerRequestExecutor extends SimpleHttpInvokerRequestExecutor {
private Map<String, String> headers;
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
#Override
protected void prepareConnection(HttpURLConnection connection, int contentLength) throws IOException {
super.prepareConnection(connection, contentLength);
if (headers != null) {
// adding our custom headers
for (String headerName : headers.keySet()) {
connection.setRequestProperty(headerName, headers.get(headerName));
}
// do not want to persist headers for another request!
headers.clear();
}
}
}
CustomRemoteExecutor:
#Component
public class CustomRemoteExecutor {
#Autowired
private HttpInvokerProxyFactoryBean factoryBean;
/*
* May be you should need a synchronized modifier here if there is possibility
* of multiple threads access here at the same time
*/
public void executeInTemplate(Map<String, String> headers, Runnable task) {
CustomHttpInvokerRequestExecutor executor = (CustomHttpInvokerRequestExecutor) factoryBean.getHttpInvokerRequestExecutor();
executor.setHeaders(headers);
task.run();
}
}
And then you can use it by below:
#Bean
#Qualifier("service")
public HttpInvokerProxyFactoryBean invoker() {
HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean();
invoker.setServiceUrl(testUrl);
invoker.setServiceInterface(Service.class);
// set our custom request executor
CustomHttpInvokerRequestExecutor executor = new CustomHttpInvokerRequestExecutor();
invoker.setHttpInvokerRequestExecutor(executor);
return invoker;
}
#Autowired
CustomRemoteExecutor executor;
#Autowired
Service service;
public void invoke(Bean bean) {
// when you need custom headers
Map<String, String> headers = new HashMap<>();
headers.put("CUSTOM_HEADER", "CUSTOM_VALUE");
headers.put("CUSTOM_HEADER2", "CUSTOM_VALUE2");
executor.executeInTemplate(headers, () -> service.process(bean));
}
There is one drawback here as I also stated in comments, if you execute your proxy service client in a multithreaded environment (server to server requests may be) you should consider to make executeInTemplate method synchronized
An addition to my answer if your service method needs to return some object then you can add another helper method to CustomRemoteExecutor and use it when you need to return something. The method can have the same name here so it can overload the former one which is much better I think.
public <T> T executeInTemplate(Map<String, String> headers, Callable<T> task) {
CustomHttpInvokerRequestExecutor executor = (CustomHttpInvokerRequestExecutor) factoryBean.getHttpInvokerRequestExecutor();
executor.setHeaders(headers);
try {
return task.call();
} catch (Exception e) {
// it is better to log this exception by your preferred logger (log4j, logback
// etc.)
e.printStackTrace();
}
return null;
}
And again you can use like below:
#Autowired
CustomRemoteExecutor executor;
#Autowired
ISampleService service;
public void invoke(Bean bean) {
// when you need custom headers
Map<String, String> headers = new HashMap<>();
headers.put("CUSTOM_HEADER", "CUSTOM_VALUE");
headers.put("CUSTOM_HEADER2", "CUSTOM_VALUE2");
// assume that service.returnSomething() method returns String
String value = executor.executeInTemplate(headers, () -> service.returnSomething(bean));
}
Hope it helps.
I am developing a rest API service with Jersey and Jetty.
It is pretty simple and I have a number of endpoints like this:
#GET
#Path("/username/{username : [a-zA-Z][a-zA-Z_0-9]}")
#Produces(MediaType.TEXT_PLAIN)
public String getUsername(#Context UriInfo uriInfo, String content) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
//Dataset<Row> df = GetDataFrame.getDF();
return "test";
}
in the getUserName method, I need to use an object which I have created in the main class.
The main class is at the moment like this:
SourceHandler source = new SparkHandler(inputSource);
source.loadIntoMemory();
Server server = new Server(8080);
ServletContextHandler ctx =
new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
ctx.setContextPath("/");
server.setHandler(ctx);
ServletHolder serHol = ctx.addServlet(ServletContainer.class, "/rest/*");
serHol.setInitOrder(1);
serHol.setInitParameter("jersey.config.server.provider.packages",
"com.ed7.res");
I would like to use the source object in the GET responses.
Is there a best practice to do that in Jersey?
Otherwise, I would create another class with a static field/static method that returns that particular object.
You can use HK2 DI. What you can do to configure it is create a standalone ServiceLocator and set that locator to be the parent locator of the app, using a Jersey property.
public static void main(String... args) {
SourceHandler source = new SparkHandler(inputSource);
ServiceLocator locator = ServiceLocatorUtilities.bind(new AbstractBinder() {
#Override
protected void configure() {
bind(source).to(SourceHandler.class);
}
});
ServletHolder serHol = ctx.addServlet(ServletContainer.class, "/rest/*");
serHol.setInitParameter(ServletProperties.SERVICE_LOCATOR, locator);
}
Then you can just #Inject the SourceHandler anywhere you need it
#Path("whatever")
public class Resource {
#Inject
private SourceHandler sourceHandler;
}
I have a Spring MVC (v4.1.3) web application with javascript UI. I have implemented a custom DispatcherServlet and configured the same in web.xml
There is a unique screen code which is sent in the HTTP Header of each request made by the UI to server.
In the doService method of my custom dispatcher servlet, I capture the HTTP Header and put the value in a ThreadLocal dto variable. I access this ThreadLocal variable in the service layer for performing some audit logic which is common for all requests.
Code from CustomDispatcherServlet:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
String uiCode = request.getHeader("uiCode");
if ((uiCode != null && !uiCode.trim().isEmpty())) {
UiCodeDto uiCodeDto = new UiCodeDto(uiCode);
final ThreadLocal<UiCodeDto> threadLocalUser = new ThreadLocal<UiCodeDto>();
threadLocalUser.set(uiCodeDto);
}
...
super.doService(request, response);
}
Code from service layer:
UiCodeDto temp = ThreadLocalUtil.getUiCodeDto(Thread.currentThread());
Code of ThreadLocalUtil to retrieve the value from ThreadLocal:
public final class ThreadLocalUtil {
public static UiCodeDto getUiCodeDto(Thread currThread) {
UiCodeDto UiCodeDto = null;
try {
Field threadLocals = Thread.class.getDeclaredField("threadLocals");
threadLocals.setAccessible(true);
Object currentThread = threadLocals.get(currThread);
Field threadLocalsMap = currentThread.getClass().getDeclaredField("table");
threadLocalsMap.setAccessible(true);
threadLocalsMap.setAccessible(true);
Object[] objectKeys = (Object[]) threadLocalsMap.get(currentThread);
for (Object objectKey : objectKeys) {
if (objectKey != null) {
Field objectMap = objectKey.getClass().getDeclaredField("value");
objectMap.setAccessible(true);
Object object = objectMap.get(objectKey);
if (object instanceof UiCodeDto) {
UiCodeDto = (UiCodeDto) object;
break;
}
}
}
} catch (Exception e) {
...
}
return UiCodeDto;
}
}
The problem is as follows -
1. I am getting random values of screen code - which means the value of some http request N is coming in http request N+1.
2. There are null DTOs in ThreadLocal variable with same name - hence, sometimes when I access the ThreadLocal in service layer, I get a null
I need help in understanding the behavior of ThreadLocal in DispatcherServlet - why would it get values of another request in doService method?
Thanks in advance.
Your code is error prone and hard to understand also why would you need a custom DispatcherServlet. A filter seems more suited for this task.
public class UiCodeFilter extends OncePerRequestFilter {
protected void doFilterInternally(HttpServletRequest req, HttpServletResponse res, FilterChain chain) {
try {
String uiCode = req.getHeader("uiCode");
if ((uiCode != null && !uiCode.trim().isEmpty())) {
UiCodeDto uiCodeDto = new UiCodeDto(uiCode);
UiCodeHolder.set(uiCodeDta);
}
chain.doFilter(req, res);
} finally {
UiCodeHolder.clear(); // Always clear!
}
}
}
The UiCodeHolder has a static ThreadLocal to keep the value.
public abstract class UiCodeHolder {
static ThreadLocal<UiCodeDto> current = new ThreadLocal<>()
public void set(UiCodeDto uiCode) {
current.set(uiCode);
}
public UiCodeDta get() {
return current.get();
}
public void clear() {
current.remove(); // for older versions use current.set(null);
}
}
In your service you can now simply do UiContextHolder.get() to obtain the correct value. The UiCodeFilter takes care of setting the value and at the end of the request clears the value again to prevent leaking.
This approach doesn't require ugly reflection hooks, is quite easy to understand is is used by Spring, Hibernate and frameworks alike.
A more Spring way of doing this is to use a request-scoped bean to extract and hold the header:
#Component
#Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UiCodeDto {
private String uiCode;
#Inject
public void setCode(HttpServletRequest req) {
uiCode = req.getHeader("uiCode");
}
public String getUiCode() {
return uiCode;
}
}
And you can use it like a normal bean:
#Service
public class RandomService {
#Inject
UiCodeDto uiCodeDto;
public void handle() {
System.out.println(uiCodeDto.getUiCode());
}
}
I'm working on a component that creates HTTP requests dynamically, and I'd like to be able to mock those requests for unit testing.
Currently the implementation looks something like this:
class ModelClass {
public void populate() {
HTTPRequest request = new HTTPRequest();
//configure request...
request.send();
}
}
Is there a way to use Guice to instantiate request so I can replace it with an instance of a mock class for testing? The nearest I can figure out would be to add an injector as instance variable of ModelClass:
class ModelClass {
private final Injector injector;
ModelClass(Injector injector){
this.injector = injector;
}
public void populate() {
HTTPRequest request = injector.getInstance(HTTPRequest.class);
//configure request...
request.send();
}
}
But that's basically like using a factory, which misses the point of Guice entirely.
You can inject a provider which provides 'HTTPRequest' instances in your code.
class ModelClass {
#Inject
Provider<HTTPRequest> httpRequestProvider;
public void populate() {
HTTPRequest request = httpRequestProvider.get();
}
}
Then, in your test code, you can mock the 'httpRequestProvider' to return mock 'HTTPRequest' instances.
Provider<HTTPRequest> mockHttpRequestProvider = mock(Provider.class);
when(mockHttpReqestProvider.get()).thenReturn(yourMockHTTPRequestObject);
// Set this mock provider to the ModelClass instance. (You may have to use reflection)
Info on injecting providers: https://github.com/google/guice/wiki/InjectingProviders
Is there an equivalent injecting Guice Providers in Simple Injector?
I need to inject a dependency into a constructor that will let me create as many instances of a dependency as needed. In guice it would look like this...
public class RealBillingService implements BillingService {
private final Provider<CreditCardProcessor> processorProvider;
private final Provider<TransactionLog> transactionLogProvider;
#Inject
public RealBillingService(Provider<CreditCardProcessor> processorProvider,
Provider<TransactionLog> transactionLogProvider) {
this.processorProvider = processorProvider;
this.transactionLogProvider = transactionLogProvider;
}
public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
// each call to get creates a new instance in Guice as per scope configs
CreditCardProcessor processor = processorProvider.get();
TransactionLog transactionLog = transactionLogProvider.get();
/* use the processor and transaction log here */
}
}
So perhaps a C# equivalent could be this inside SimpleInjector?
private readonly MailSender _mailSenderProvider;
public MailService(Func<MailSender> mailSenderProvider)
{
_mailSenderProvider = mailSenderProvider;
}
public void SendMail()
{
var mailSender = _mailSenderProvider.Invoke();
mailSender.SendSomeMail("Hello world");
}
I tried injecting Func in my real code and got this...
{"No registration for type BootStrapper could be found and an implicit registration could not be made. The constructor of type BootStrapper contains the parameter of type Func with name 'storeType' that is not registered. Please ensure Func is registered in the container, or change the constructor of BootStrapper."}
You need to explicitly configure factory delegates with Simple Injector (see here)
var container = new Container();
container.Register<MailSender>();
container.RegisterSingle<Func<MailSender>>(() => container.GetInstance<MailSender>());
You may want to consider separating concerns by adding a new abstraction. If you define an IMailSender you can then create a MailSenderProxy that is responsible for ensuring a new MailSender instance for each message.
public interface IMailSender {
void Send(string message);
}
public class MailSender : IMailSender {
public void Send(string message) {
}
}
public class MailSenderProxy : IMailSender {
private readonly Func<IMailSender> mailSenderFactory;
public MailSenderProxy(Func<IMailSender> mailSenderFactory) {
this.mailSenderFactory = mailSenderFactory;
}
public void Send(string message) {
this.mailSenderFactory().Send(message);
}
}
This abstracts away the requirement of creating a new MailSender for each mail (this is possibly not something the MailService should know about)
public class MailService {
private readonly IMailSender sender;
public MailService(MailSender sender) {
this.sender = sender;
}
public void SendMail() {
this.sender.Send("Message");
}
}
The Container configuration would look something like this
var container = new Container();
container.Register<MailSender>();
container.RegisterSingle<Func<IMailSender>>(() =>
container.GetInstance<MailSender>());
container.Register<IMailSender, MailSenderProxy>();
container.Verify();
I found the following example in the SimpleInjector docs
http://simpleinjector.readthedocs.org/en/latest/howto.html#register-factory-delegates
public static void AllowResolvingFuncFactories(this ContainerOptions options)
{
options.Container.ResolveUnregisteredType += (s, e) =>
{
var type = e.UnregisteredServiceType;
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>))
{
return;
}
Type serviceType = type.GetGenericArguments().First();
InstanceProducer registration = options.Container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType,
registration.BuildExpression()).Compile();
e.Register(Expression.Constant(factoryDelegate));
};
}
Then on my container I call this...
// Allow types of Func<T> to be resolved
container.Options.AllowResolvingFuncFactories();
// 3. Optionally verify the container's configuration.
container.Verify();
Now I can inject Func< MyClass > and when I invoke the Func it returns as many instances as I want of that type.
All thanks to C# reified types and Simpleinjector's awesome api!