Atmosphere framework, BroadcasterFactory.getDefault() alternative - java

I am using Atmosphere framework and it looks in the newest version(s) of the library the method:
BroadcasterFactory.getDefault() is depricated. (and this method was essentially used everywhere and I cannot find an example how to use the new "way" )
The javadoc states :
#deprecated Use {#link org.atmosphere.cpr.AtmosphereConfig#resourcesFactory()}
However I cannot find a single documentation how to get the AtmosphereConfig to be able to get the resourceFactory (which is an instance method).
Can someone tell me how to get the config .. or the AtmosphereFramework object itself from which I can get the config or any example which is up2date ?

Not sure if it works, but try to get ServletContext and use getAttribute(AtmosphereFramework.class.getName()) to obtain AtmosphereFramework. If you are using Spring, try to autowire AtmosphereFramework directly.
You can also get BroadcasterFactory from AtmosphereResource and then lookup for Broadcaster like:
private String path;
private BroadcasterFactory broadcasterFactory;
#Ready(value = Ready.DELIVER_TO.ALL)
public void onReady(final AtmosphereResource r) {
System.out.println("onConnect");
r.addEventListener(new AtmosphereConnectionController());
if(broadcasterFactory == null){
path = r.getBroadcaster().getID();
broadcasterFactory = r.getAtmosphereConfig().getBroadcasterFactory();
}
}
//later in code
broadcasterFactory.lookup(path).broadcast("message");

Use dependency injection. In my project, it goes like this:
#MeteorService(path = "/recursos/fila-de-atendimento", interceptors = {AtmosphereResourceLifecycleInterceptor.class})
public class FilaDeAtendimentoResource extends HttpServlet {
#Inject
private BroadcasterFactory broadcasterFactory;
...
/** Used for registering for a message */
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
...
Broadcaster broadcaster = broadcasterFactory.lookup(broadcasterId, true);
meteor.setBroadcaster(broadcaster);
...
}
}

Related

What are the types of classes/instances I can inject a CDI event into?

I want to have a class that can fire an event. Ideally, I'd like to have it in a POJO (dealing with legacy code that's in POJOs) but I know that's not possible. So instead, I'd like to have something that the POJOs can call which can fire the event.
NOTE: I'm on Tomcat with CDI, JPA also installed (It is not an option to switch to a full EE server on this project)
I'm not sure if it should be a singleton/app-wide-singleton, or should be per request (or even session). So my questions are:
What can an event be injected into? (e.g. #WebListener, #Singleton, RequestScoped, #Stateless)
Which one makes the most sense for this use case?
how would a POJO get access to that class/instance (the POJO is called from a servlet)?
Sample Code:
//Is this correct?
#WebListener
public class EventHandler
{
#Inject
#MyEventQualifier
private Event<MyEvent> myEvent;
public void fireEvent(MyEvent anEvent)
{
myEvent.fireAsync( anEvent );
}
}
The fundamental container classes are your standard "managed" objects, like the one you listed (WebListeners, Filters, Servlets). These act as the root of the context chain. Since those are managed by CDI, anything that they Inject are also managed, and on down that line.
If your Servlet (for example) injects PojoX, PojoX can inject PojoY, and on and on. The game is to avoid new and use CDI constructs instead to create your POJOs.
As for hurdling the legacy POJO/CDI divide, you could do a couple of things.
You could inject an instance of EventHandler in to the Servlet, and then pass that instance in to the POJO as a parameter.
You can stick that instance in to the request as an attribute, or shove the instance in to the ServletContext when the Servlet is first created.
You can make EventHandler an #Singleton and in its #PostConstruct set a static variable that can be returned via a standard, static getInstance call.
You can have your POJO call the container directly to do the lookup (or call a utility function).
And, of course, if the POJO can be injected itself, just do it that way.
Addenda for the comment:
You can simply inject the POJO, if that's appropriate for you work.
Here's an example:
#WebServlet(name = "NewServlet", urlPatterns = {"/NewServlet"})
public class NewServlet extends HttpServlet {
#Inject
Instance<Pojo> pojoInstance;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Pojo pojo = pojoInstance.get();
String world = pojo.getWorld();
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet NewServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet NewServlet at " + request.getContextPath() + "</h1>");
out.println("<p>Hello " + world);
out.println("</body>");
out.println("</html>");
}
}
}
public class Pojo {
#Inject
Event<PojoEvent> pojoEventHdlr;
#PostConstruct
public void postConstruct() {
System.out.println("Look, another Pojo!");
}
public String getWorld() {
PojoEvent pe = new PojoEvent("World event pojo fired");
pojoEventHdlr.fire(pe);
return "world";
}
}
public class PojoEvent {
String msg;
public PojoEvent() {
}
public PojoEvent(String msg) {
this.msg = msg;
}
public String toString() {
return "PojoEvent with msg: " + msg;
}
}
#Singleton
public class SingletonPojo {
public void pojoEventObserver(#Observes PojoEvent pe) {
System.out.println("We got a PojoEvent " + pe);
}
}
The important thing to note, is that I injected an Instance<Pojo> in to the servlet, and then used Instance.get on it, rather than just the Pojo directly. The reason for that is Servlet are nominally Singletons within the web app, so if you injected an actual Pojo, all of your requests would use the exact same instance of the Pojo (unlikely what you want).
You can see the Pojo fires the event, and I have a #Singleton class observing the event and dumping out the message.
If you're willing to make changes to you legacy code, you can do what you like and there's no real need to jump through hoops to bridge the CDI <-> legacy divide. Just roll them in to CDI as necessary.

Jersey: Detect when Controller Class is Created

I've implemented a JAX-RS server application using Jersey 2.24.
I use the Guice-HK2 bridge so that the controller classes (those annotated with #Path) are injected with dependencies from Guice, not Jersey/HK2.
However, HK2 still creates instances of the #Path annotated classes itself.
Is there a way I can plug into Jersey/HK2 so that I'm notified when a #Path annotated class is created? Like some sort of lifecycle listener? Every time a #Path annotated class is created by Jersey/HK2 I want to do some registering/logging of that class.
If Guice were doing the actual creation of the #Path annotated class I think I could do it using a generic Provider but that's not available in this case, since Jersey/HK2 is creating the actual instance.
Thank you!!
I think the least intrusive way would be to just use AOP. HK2 offers AOP. What you can do is create a ConstructorInterceptor. Something like
public class LoggingConstructorInterceptor implements ConstructorInterceptor {
private static final Logger LOG
= Logger.getLogger(LoggingConstructorInterceptor.class.getName());
#Override
public Object construct(ConstructorInvocation invocation) throws Throwable {
Constructor ctor = invocation.getConstructor();
LOG.log(Level.INFO, "Creating: {0}", ctor.getDeclaringClass().getName());
// returned instance from constructor invocation.
Object instance = invocation.proceed();
LOG.log(Level.INFO, "Created Instance: {0}", instance.toString());
return instance;
}
}
Then create a InterceptorService to only use the interceptor for classes annotated with #Path
public class PathInterceptionService implements InterceptionService {
private static final ConstructorInterceptor CTOR_INTERCEPTOR
= new LoggingConstructorInterceptor();
private final static List<ConstructorInterceptor> CTOR_LIST
= Collections.singletonList(CTOR_INTERCEPTOR);
#Override
public Filter getDescriptorFilter() {
return BuilderHelper.allFilter();
}
#Override
public List<MethodInterceptor> getMethodInterceptors(Method method) {
return null;
}
#Override
public List<ConstructorInterceptor> getConstructorInterceptors(Constructor<?> ctor) {
if (ctor.getDeclaringClass().isAnnotationPresent(Path.class)) {
return CTOR_LIST;
}
return null;
}
}
Then just register the InterceptionService and ConstructorInterceptor with the DI system
new ResourceConfig()
.register(new AbstractBinder(){
#Override
public void configure() {
bind(PathInterceptionService.class)
.to(InterceptionService.class)
.in(Singleton.class);
bind(LoggingConstructorInterceptor.class)
.to(ConstructorInterceptor.class)
.in(Singleton.class);
}
});
See complete example in this Gist
See Also:
HK2 documentation on AOP

Jersey Endpoint+OSGi Dependency, Keeping Track

I have a Jersey endpoint which uses a custom OSGi Service ExceptionManager Service.
#Path("service")
public class ServiceFacade {
private volatile ExceptionManager exceptionManager;
public ServiceFacade() {
BundleContext bC = FrameworkUtil.getBundle(ServiceFacade.class).getBundleContext();
ServiceReference<ExceptionManager> sR = bC.getServiceReference(ExceptionManager.class);
if (sR != null)
this.exceptionManager = bC.getService(sR);
}
#GET
#Consumes({MediaType.APPLICATION_JSON})
#Produces(MediaType.APPLICATION_JSON)
public Response sayHello() {
try {
if (exceptionManager == null)
return Response.status(Status.SERVICE_UNAVAILABLE).build();
// Do some work...
} catch (Exception e) {
exceptionManager.handle(e);
}
}
}
This Jersey class is added to the Jersey Application as a simple class, that means that every time a user hits this endpoint, a new instance of this class is created to handle the request. As you can see, the class contains a constructor which initializes the ExceptionManager Service. My question is, isn't there a simplified way of retrieving the service without going to BundleContext?
I have seen DependencyManager, but this bundle seems to only add the dependencies to the class (ServiceFacade in this case) during the Activation process, but that dependency resolution is too early this has to be done during run-time, every time an instance is created. Bellow is an approximation with DependencyManager but is not a solution for this:
public class Activator extends DependencyActivatorBase {
#Override
public void init(BundleContext bundleContext, DependencyManager dependencyManager) throws Exception {
dependencyManager.add(createComponent()
.setImplementation(ServiceFacade.class)
.add(createServiceDependency()
.setService(ExceptionManager.class)
.setRequired(true));
}
}
Thanks.-
You can obtain the reference to an OSGi service without accessing to BundleContext by using Declarative Services. A tutorial can be found here.
You can make the endpoint a singleton resource. This way you can let the dependency manager create a single instance and inject services and then add that instance to the Jersey application.
There are a few limitations, like Jersey's field or constructor injection does not work. You also have to be careful about concurrency when using fields of the resource.

Make a static variable injectable

i am building a http API client that needs to call out to a specific endpoint like so:
public class MyApiClient {
private static final String ENDPOINT ="http://myapi....";
}
Here the endpoint won't change so its constant. However, I want to be able to override this for testing so that I can test against a mock http server for example.
Whats the best way to do this? Is it just to make it an instance variable and provide it with a starting value:
private String endpoint = ="http://myapi....";
public void setEndpoint(String endpoint){
...
}
Well, there are of course many solutions to this and one way of doing it is to use a system property with a default value:
private static final String DEFAULT_ENDPOINT = "http://myapi....";
private static final String ENDPOINT =
System.getProperty("my.endpoint", DEFAULT_ENDPOINT);
This way you get a configurable way of solving your problem. If you need even more flexibility when initializing your static constants you could also use a static initializer:
private static final String ENDPOINT;
static {
// do initialization here but do not throw any exceptions (bad practice)
// you can e.g. read from files etc...
// Then assign your constant...
ENDPOINT =
}
System properties are passed on the command line as -D parameters e.g:
java -Dmy.endpoint=http://...
But in my opinion, an even better approach is to actually inject the value to the class that is using it:
public class ClassThatIsUsingTheConfig {
private final String endpoint;
public ClassThatIsUsingTheConfig(final String endpoint) {
this.endpoint = endpoint;
}
public void someMethod() {
// use endpoint
}
}
And then, make the selection of which endpoint to use in the caller class. From a test case, this will be very easy to mock.
public class MyTest {
#Test
public void testMethod() {
ClassThatIsUsingTheConfig var = new ClassThatIsUsingTheConfig(TEST_ENDPOINT);
var.someMethod();
}
}
public class MyProdClass {
public void prodMethod() {
ClassThatIsUsingTheConfig var = new ClassThatIsUsingTheConfig(PROD_ENDPOINT);
var.someMethod();
}
}
You can read more about dependency injection here.
On a side note, if you are using some kind of framework for managing dependencies such as Spring Framework or CDI it is common to be able to inject properties and constants in various ways (e.g. based on which environment that is currently running). An example, when using Spring Framework you can declare all your constants in a property file and inject the property using annotations:
#Autowired
public ClassWhoIsUsingTheConfig(#Value("my.endoint") final String endpoint) {
this.endpoint = endpoint;
}
The property file for prod could be along the lines of:
my.endpoint=http://prodserver...
wheras the property file for test would look like this:
my.endpoint=http://testserver...
The approach of using a Dependency Injection engine allows for a very flexible way of handling external constants, paths, resources etc and simplifies your life when it comes to testing the code.

Endpoint Injection with Apache Camel

I use Apache Camel for a projet and I would like to use the produce annotation to send an object in a file.
First, is it possible ? Is there a better way ?
Secondly, I tried this snippet code:
public class MyProducer {
private static final String MEDIA = "file:";
private static final String PATH = "c:/directory";
#Produce(uri = MEDIA + PATH)
protected ProducerTemplate producer;
public void publish(MyObject o) {
producer.sendBody(o);
}
}
When I call the publish methode the producer is not inject (null). Anybody have an idea ?
Thanks in advance.
It depends on how you create the MyProducer class. You have to define it inside a spring context as a spring bean to make the annotations work.

Categories