How to expose an EJB as a web service that is not transactional? - ejb

I have an EJB (coded using Java EE 6 annotations) that is defined as follows:
#Stateless
#WebService
public class SecurityWebService {
public void registerUser(RegistrationRequest request) {
...
}
}
Note that this EJB is also exposed as a web service. However, I am running into an issue with the generated web service. The WSDL generated by my container (GlassFish) contains WS-Atomic Transaction policies because a stateless session bean by default is transactional (see details here). Unfortunately my .NET client is choking on the WSDL because it does not understand WS-AT policies.
So what I really want is a nice-clean web service that is not transactional, but the associated EJB should be transactional (it has to insert records in the database). How do I do this? The only approach I can think of is to create a "normal" web service that passes all its calls to an EJB like this - not elegant at all:
#WebService
public class SecurityWebService {
#Inject
private SecurityService securityService;
public void registerUser(RegistrationRequest request) {
securityService.registerUser(request);
}
}
#Stateless
public class SecurityService {
public void registerUser(RegistrationRequest request) {
...
}
}
Is there a better way?
Thanks.
Naresh

You can try annotating the method:
#TransactionAttribute(TransactionAttributeType.NEVER)
or
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Dunno if the web service will pick that up or not, but it's worth a shot.
Edit for comment:
Did you try REQUIRES_NEW? They may well not propagate back out to the web service.
Otherwise, yea, you'll be stuck facading the transactional part with the non-transactional web service.

Related

Cloud datastore dynamic namespace

Requirement
For Cloud, datastore needs to change namespace dynamically. (example store kind as per company Name)
Used Spring cloud DataRepository with Springboot for same
Issue
We need to declare spring.cloud.gcp.datastore.namespace in application.properties which is static.
Is there any way to change this dynamically with CRUDReposity of spring cloud
Thanks in advance
You can change anything you want in your application.properties at runtime using Spring Cloud Config.
Spring Cloud Config provides server-side and client-side support for externalized configuration in a distributed system. With the Config Server, you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring Environment and PropertySource abstractions, so they fit very well with Spring applications but can be used with any application running in any language.
Just as a quick example on how you can use this , you should firstly add the dependency : eg gradlecompile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '1.1.1.RELEASE', then you need to add the #RefreshScope on the desired configuration bean.
You will be able to view your current config at a certain endpoint, like "applicationConfig: [classpath:/application.properties]": {
"my.property": "value1",
etc
And then you can change the properties as you wish doing a POST request like :
curl -X POST http://localhost:8080 -d my.property=value2
There is also a nice article about dynamically reloading the properties in a Spring application here. It is nice because they actually display more ways that you can achieve that.
You can use DatastoreNamespaceProvider which can dynamically return needed namespace.
Was added in this PR PR
Also see this discussion here and this recommendation
#Component
#RequiredArgsConstructor
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class HeaderValueProvider implements Supplier<String>, DatastoreNamespaceProvider {
private final HttpServletRequest httpServletRequest;
#Override
public String get() {
return httpServletRequest.getHeader("someHeader");
}
}
And this
#Component
public class UserContextProvider implements DatastoreNamespaceProvider, Consumer<UUID> {
private static final ThreadLocal<UUID> USER_CONTEXT = new ThreadLocal<>();
#Override
public String get() {
return ofNullable(USER_CONTEXT.get())
.map(UUID::toString)
.orElse(null);
}
#Override
public void accept(UUID uuid) {
USER_CONTEXT.set(uuid);
}
}

Run a code when the war is deployed [duplicate]

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?

Spring Cloud Netflix : Passing host request parameter via RequestInterceptor to FeignClient

I am building a Spring Cloud project (Brixton.M4 with Spring Boot 1.3.1) with Eureka, Zuul and FeignClient where I am trying to add multi tenancy support (Tenants are identified by subdomain : tenant1.myservice.com). To do so, I would like to somehow pass the original subdomain along requests that are forwarded from a service to the other via Feign but I can't seem to be able to find the right way to do it.
What I have is a client that exposes a #RestController which calls a #FeignClient to communicate with my backend which exposes server operations to the client through its own #RestController.
The #FeignClient using same interface as my #RestController on the server :
#FeignClient(name = "product")
public interface ProductService extends IProductService {
}
What I am currently trying to do is set a header in a RequestInterceptor :
#Component
public class MultiTenancyRequestInterceptor implements RequestInterceptor {
private CurrentTenantProvider currentTenantProvider;
#Autowired
public MultiTenancyRequestInterceptor(CurrentTenantProvider currentTenantProvider) {
this.currentTenantProvider = currentTenantProvider;
}
#Override
public void apply(RequestTemplate template) {
try {
template.header("TENANT", currentTenantProvider.getTenant());
} catch (Exception e) {
// "oops"
}
}
}
My provider class is a simple component where I'm trying to inject a request / session scope bean :
#Component
public class CurrentTenantProvider {
#Autowired
private CurrentTenant currentTenant;
//...
}
The bean (I tried both session and request scope) :
#Bean
#Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public CurrentTenant currentTenant() {
return new CurrentTenant();
}
On the server, I use Hibernate multitenant provider that is supposed to catch the header value and use it to define which DB to connect to :
#Autowired
private HttpServletRequest httpRequest;
#Override
public String resolveCurrentTenantIdentifier() {
return httpRequest.getHeader("TENANT");
}
It seems the Feign call to the server is done in another thread and out of the incoming request scope, so i'm not sure how to pass that value along.
It all works fine when I hardcode the tenant value in the RequestInterceptor so I know the rest is working properly.
I have also looked at many other posts about Zuul "X-Forwaded-For" header and cannot find it in the request received on the server. I have also tried adding a ZuulFilter to pass host name to next request but what I see is that original request to the Client is picked up by the ZuulFilter and I can add but not when the Feign request is sent to the backend service even if I map it in zuul (i guess that is intended ?).
I am not really sure what's the next step and would appreciate some suggestions.
Hope that it's of any use for you but we're doing sth similar in Spring-Cloud-Sleuth but we're using a ThreadLocal to pass span between different libraries and approaches (including Feign + Hystrix).
Here is an example with the highlighted line where we retrieve the Span from the thread local: https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java#L123

Problems integrating NServiceBus with ServiceStack IRequiresRequestContext

I am looking to integrate NServiceBus into an existing ServiceStack web host. ServiceStack is currently using the built in Funq IoC container. NServiceBus has been configured (elsewhere in the system) to use Unity for IoC.
ServiceStack has a feature whereby IRequestContext will be automatically injected when it finds the IRequiresRequestContext interface on a class. NServiceBus has a similar feature for Message Mutators, via the IMutateOutgoingTransportMessages interface.
The application is a multi-tenant application. Single application, which via an API Key, passes an account code through to the NServiceBus handler (indirectly via a provider that is called on the construction of the handler's constructor injection using Unity).
My problem arises in ServiceStack. I am using a request filter to drag the API key out of the request headers, which I look-up in a database, and then finally write into the IHttpRequest.Items collection:
appHost.RequestFilters.Add((req, res, requestDto) =>
{
var tenant = tenantRepository.GetByApiKey(
req.Items.Add("AccountCode", tenant.AccountCode);
}
I then have an NServiceBus transport message mutator, that implements that IRequiresRequestContext interface, and this class is located in the same assembly as the ServiceStack services registered in the AppHost:
public class MessageHeaderMutator : IMutateOutgoingTransportMessages, INeedInitialization, IRequiresRequestContext
{
#region IRequiresRequestContext Members
public IRequestContext RequestContext { get; set; }
#endregion
#region IMutateOutgoingTransportMessages Members
public void MutateOutgoing(object[] messages, NServiceBus.TransportMessage transportMessage)
{
transportMessage.Headers.Add("AccountCode", RequestContext.Get<IHttpRequest>().Items["AccountCode"].ToString());
}
#endregion
#region INeedInitialization Members
public void Init()
{
Configure.Instance.Configurer.ConfigureComponent<MessageHeaderMutator>(DependencyLifecycle.InstancePerCall);
}
#endregion
}
However, RequestContext is never injected, and is always null. My theory is that the two interface injections, injected via the two separate frameworks, are somehow clashing.
I have a workaround, which is to use the ServiceStack HostContext.Items instead, as per this discussion, but I am concerned that the HostContext is not a per request collection, so I might end up writing data to the wrong tenant. Workaround is:
// app host
appHost.RequestFilters.Add((req, res, requestDto) =>
{
var accountCode = tenantRepository.GetByApiKey(
HostContext.Instance.Items.Add("AccountCode", client.AccountCode);
}
// message mutator
public class MessageHeaderMutator : IMutateOutgoingTransportMessages, INeedInitialization
{
#region IMutateOutgoingTransportMessages Members
public void MutateOutgoing(object[] messages, NServiceBus.TransportMessage transportMessage)
{
var accountCode = HostContext.Instance.Items["AccountCode"].ToString();
transportMessage.Headers.Add("AccountCode", accountCode);
}
#endregion
#region INeedInitialization Members
public void Init()
{
Configure.Instance.Configurer.ConfigureComponent<MessageHeaderMutator>(DependencyLifecycle.InstancePerCall);
}
#endregion
}
My question is therefore twofold:
The first is, why does IRequiresRequestContext not correctly inject RequestContext into the Message mutator, or is there a way to inject RequestContext manually?
Is the use of the HostContext safe to assume it is per request?
Bonus question: Is the use of two separate IoC containers in the same project (Unity in NServiceBus and Funq in ServiceStack) a really bad idea? Would it be smarter to get ServiceStack to use the same Unity IoC container as NServiceBus?
P.S. This is NServiceBus 4 (beta at time of writing).
It is precisely because you're using 2 different containers that DI doesn't work for you out of the box for objects registered in different containers.
You don't necessarily need to standardize on a single container (though it would save you from dealing with these sorts of issues all the time).
What you can do to keep working with both containers is to tell the NServiceBus container how to resolve IRequiresRequestContext like this:
public class RequestContextBootstrapper : INeedInitialization
{
public void Init()
{
Configure.Component<IRequiresRequestContext>( /* get object from ServiceStack */ );
}
}
You can access the ServiceStack container via AppHostBase.Container and use it to resolve your objects as Udi suggested.

Using special auto start servlet to initialize on startup and share application data

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?

Resources