Java Jersey RESTful services - java

Rather new to REST and Jersey, and I'm trying out some basic examples. I've got one particular question though, which I haven't really found an answer for yet (don't really know how to look for this): how would you go about storing/defining common services so that they are stateful and accessible to all/some resources?
For instance, a logger instance (Log4J or whatever). Do I have to manually initialize this and store it in the HttpSession? Is there a "best practice" way of doing this so that my logger is accessible to all/some resources?

Your best option is to inject the services into the Resource using something like Spring. Adding a setter in your Resource for the particular service makes it available for various scopes. The following tutorial explains in detail how to use Spring and Jersey. Below are examples of the various pieces needed to make this work. Specifically answering your question however the "best practice" is to allow Spring to manage the "stateful"ness or "scope" of a particular service.
Simple Service Bean
public class SimpleBean {
private int counter;
public String sayHello() {
return Integer.toString(counter++);
}
}
Simple JAX-RS Resource
public class HelloWorldResource {
private SimpleBean simpleBean;
public void setSimpleBean(SimpleBean simpleBean) {
this.simpleBean = simpleBean;
}
#GET #Path("/Hello") #Produces(MediaType.APPLICATION_JSON)
public String sayHello() {
return "{\"Hello\": \"" + this.simpleBean.sayHello() + "\"}";
}
}
Simple Spring applicationContext.xml, notice the "scope" for the Bean and Resource. This defines how stateful these objects are.
<bean id="simpleBean" scope="prototype" class="myhealth.spring.SimpleBean"/>
<bean id="helloWorldResource" scope="singleton" class="myhealth.ajax.HelloWorldResource">
<property name="simpleBean">
<ref bean="simpleBean"/>
</property>
</bean>

Speaking strictly about the Logger, are you sure you want it to be stateful? Most projects I've been on just grab one in whatever class needs it
Logger log = Logger.getLogger(this.getClass().getName());
Cut and paste that everywhere and let the logging magic begin!
To your original question regarding keeping state: Are you looking to keep something stateful per user (like a session) or some other state across the application (like a runtime configured logger)? Sessions can be managed with the HttpRequest and some ServletFilters. Grab the request in your JErsey code like so
#Path("/awesome")
public class AwesomeService {
#GET
#Produces("text/awesome")
public String getAwesome(#Context HttpServletRequest req) {
HttpSession session= req.getSession(true);
//brilliance
}
}
Application resources, like an entity manager or a konfabulator can be initialized statically and used as Singletons or with Factories.
class EntityManager {
EntityManager manager;
public static EntityManager getManager() {
if(manager == null) {
manager = initManager();
}
return manager;
}
}

Related

Is there a way to access SlingRepository in a POJO?

Is there a way to access SlingRepository in a POJO that is not managed by OSGI?
For example, we might have a POJO named Site:
public class Site {
private String domainName;
public String getDomainName() { return domainName; }
public void setDomainName(String domainName) { this.domainName = domainName; }
public void validate() throws Exception {
SlingRepository repo = ...;
// validation logic dependent on repo
}
}
That is used like this:
Site site = new Site();
site.validate();
Update (re. Tomek's answer)
The reason why I cannot use #Reference or the current request's ResourceResolver is because I am trying to implement a JSR-303 (aka Bean validation) validator.
In our Sling app, we have a bunch of servlets that receive JSON payloads from the browser. Then we convert them to pojos:
Person p = new Gson().fromJson(json, Person.class)
validate(p); // Validate p using Bean Validation
Person is a simple POJO annotated with JSR-303 annotations:
public class Person {
#NotNull
private String name;
#UniqueProperty(
name = "email",
path = "/content/myapp",
nodeType = "cq:PageContent"
)
private String email;
}
In short, my goal is to implement the #UniqueProperty validation. In the example above, if a node of type cq:PageContent under /content/myapp exists that has an email property with the same value as this model, the validation fails.
The validator class itself will look like this:
public class UniquePropertyValidator implements ConstraintValidator<UniqueProperty, String {
#Override
public void initialize(UniqueProperty constraintAnnotation) {
...
}
#Override
public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
// need to execute a JCR query here
}
}
UniquePropertyValidator will be instantiated by the JSR-303 implementation (e.g. Hibernate Validator) as needed, and there's no way it can access the current request's resource resolver, hence why I was looking for a way to access the SlingRepository.
First of all, if you use Sling then using ResourceResolver is generally more preferable than SlingRepository. It gives you an useful Resource abstraction layer and you can still get the underlying JCR Session object using adaptTo() method.
But back to your question, POJO always lives in a context, there is some entrypoint that runs the whole thing. In Sling there is a few such places: JSP, servlet or an OSGi component. In all of these entrypoints there is at least one way to get access to the repository:
JSP
use resourceResolver binding
use getService(ResourceResolverFactory.class) to create an administrative resolver,
Servlet or filter
use request.getResourceResolver() to get the request session,
or see the next point.
Any OSGi service (including servlet or filter)
use #Reference ResourceResolverFactory to get the factory and create administrative resolver.
After that you can pass the resource resolver to your POJO constructir. I think it's a better option than using hacks with the FrameworkUtil for a few reasons:
if you pass the ResourceResolver to the POJO constructor, it's clear that this particular class operates on the repository,
you don't need to worry about closing sessions (as POJO may not have a defined lifecycle),
if you create your POJO in servlet or component (cases 1 and 2), it's better to use the request's session to avoid working on the administrative one.
In general you should not retrieve external resources from a pojo. Simply add a contructor or setter where you inject the SlingRepository at the position where you do the new. This has the advantage that your pojo is independent of OSGi and can be used in different environments. Also unit testing is easier with this approach.
Site site = new Site(slingRepository);
Of course this just moves the problem to the class that creates the instance. I guess at some point you start at an activator where you have access to the BundleContext and can lookup the service.
In the rare cases where you really want to lookup a service directly use
FrameworkUtil.getBundle(this.getClass()).getBundleContext();
From there you can lookup the service.
As Christian Schneider wrote, you can use this:
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
ServiceReference serviceReference = bundleContext.getServiceReference(SlingRepository.class);
SlingRepository slingRepository;
if (serviceReference != null) {
slingRepository = (SlingRepository) bundleContext.getService(serviceReference);
}
Just found a solution how you can tap into the lifecycle of the ConstraintValidator.
See:
http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-validationimplementation
Chapter 2.5. The ConstraintValidatorFactory might help you. If you register a ConstraintValidatorFactory in e.g. your Activator then you can supply it with the SlingRepository. The factory can then forward the SlingRepository to the Validator it creates. So you can keep the OSGi logic out of the Validator.

#EJB workflowDao is null in service layer

I'm trying to figure out how to setup a Service/Dao layer in my application. I've found a few dozen resources all with different ways on how to do it and decided to follow the model found here: How should EntityManager be used in a nicely decoupled service layer and data access layer?
I can't figure out what I'm missing that's causing this NPE.
Usage:
#Path("/helloworld")
public class MyController {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
WorkflowService workflowService = new WorkflowService();
workflowService.save(workflow);
return "Workflow ID:";
}
}
My Dao:
#Stateless
public class WorkflowDao {
#PersistenceContext(unitName = "unit")
private EntityManager entityManager;
public int save(Workflow workflow) {
entityManager.persist(workflow);
return workflow.getId();
}
}
My Service:
#Stateless
public class WorkflowService {
#EJB
WorkflowDao workflowDao;
public int save(Workflow workflow) {
int id = workflowDao.save(workflow); //throws NullPointerException because workflowDao is null
return id;
}
}
This is my first time setting up a Java project (only have worked on 1 before and it used Spring) so please keep that in mind if this looks horribly wrong.
WorkflowDao is not an EJB, it's a POJO with a#Stateless annotation. So naturally, injecting it with #EJB fails, creating a null workflowDao attribute and eventually producing a NullPointerException.
To make WorkflowDao into a full-fledged EJB, besides having a #Stateless or #Stateful annotation it needs to implement a local, remote or both interfaces, and those interfaces must be annotated respectively with #Local and #Remote. Please refer to the tutorial for details.
Also, quite possibly (this can be application server-dependent) you'll have to register the EJB in the application's xml descriptor files - for instance, in web.xml's <ejb-local-ref> element.
As a side note - it's not a good idea to use an EJB as a DAO, an EJB is typically used for implementing business logic (true, persist/merge operations can be called from here) but the actual persistence layer nowadays is implemented using JPA. In other words, WorkflowService should be the EJB service, there's no need to inject an EJB into it, and there's no need for a separate DAO layer - JPA entities fulfill this role.
If you instantiate your WorkflowService manually, the container wont perform any injection, since your WorkflowService is not managed by the Container.
I suggest you:
Annotate your Jax-RS Resource #Stateless
Inject your WorkfloService via #EJB as a member
Implementing a Local or Remote Interface is not necessary anymore
#Path("workflows")
#Stateless
public class WorkFlowResource{
#EJB
WorkflowService workflowService;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
workflowService.save(workflow);
return "Workflow ID:";
}
}

EJB3 correlation ID

Now my colleagues work on logging subsystem and they want to bind separate operations, that was initiated from some business method. For example, if method from bean A calls to some method in bean B and then in bean C it will be great to know than business methods in bean B and bean C does some staff for method from bean A. Especially it will be great to know that methods from B and C done some unit of work for concrete call of bean A.
So, the question is how to tie this units of work into something total? Obviously, it is not beautiful to use method arguments for binding!
And also I think that it is time to ask another question, that is close enough to previous one. What if I want to propagate some context information from bean A to another beans, that are called from A? Something like security credentials and security principal? What can I do?
May be questions that I asked is some kind of bad practice?
Looks like a good use case for mdc, available in both Logback and Log4J. Essentially you are attaching some custom value to a thread and all logging messages comming from that thread can attach that value to the message.
I think the best way to implement this in EJB will be an interceptor:
public class MdcInterceptor {
#AroundInvoke
public Object addMdcValue(InvocationContext context) throws Exception {
MDC.put("cid", RandomStringUtils.randomAlphanumeric(16));
try {
return context.proceed();
} finaly {
MDC.remove("cid");
}
}
}
Now all you have to do is add:
%X{user}
to your logging pattern (logback.xml or log4j.xml).
See also
Logging user activity in web app
For general purpose context information you can use TransactionSynchronizationRegistry. It could look something like this:
#Stateless
public class MyBean {
#Resource
TransactionSynchronizationRegistry registry;
#AroundInvoke
public Object setEntryName(InvocationContext ic) throws Exception {
registry.putResource(NAME, "MyBean");
return ic.proceed();
}
}
#Stateless
public class MyBean2 {
#Resource
TransactionSynchronizationRegistry registry;
public void doJob() {
String entryName = (String)registry.getResource(NAME);
...
}
}
I believe it is usually implemented using ThreadLocal variables as normally each transaction maps to a sigle thread in application servers. So if TransactionSynchronizationRegistry is not implemented in your AS (like e.g. in JBoss 4.2.3) or you need lower level tool, you could use ThreadLocal variables directly.
BTW I guess that MDC utilities use the same thing under the covers.

Best way to interact with EJBs in Java EE

I have a moderate sized Java EE 6 project that uses several EJBs, including one which sole purpose is managing database calls through JPA. My question is what is the best way to add a new class that does some random bit of functionality and then calls the database access EJB to persist the data from this class.
Does this new class have to be an EJB if it needs access to annotations and injections? Does it have to be an EJB if it has to be deployed with the rest of the project?
I was told that if you want to add a new logic class to the project it either has to be an EJB or you can remotely integrate it using JNDI to access EJB elements and create some kind of client interface. Right now my new class is just a POJO but it's not able to access the EJB functionality.
What should I do in general?
EDIT: Please note my question IS NOT about database access. That's just an example I'm using. My guestion is more broad. I want to know how to access EJB methods from other classes I create. From one EJB to another you can simply inject the other EJB since they're both container managed. But say I create another class in the same package as the EJBs how might How can I access those methods? Is it possbile? What is the best practices here.
Right now I have a class that is taking twitter feed data from a URL it then parses the JSON and returns a string of the top 10 entries. I want to call my EJB that manages database access and pass that string to its corresponding method but I cannot do that because my class is not also an EJB.
EJBs are generally used to implement services of any kind. They integrate really well with JPA so are often used for DB access, but that's not their only usage.
What EJBs are typically not suited for is modeling data. I.e. they should be the verbs in your application, not the nouns. The following is thus wrong:
#Stateless
#Entity
public class CreditCard { // silly, don't do this!
#Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
The following is better, it's a service that when your application starts up fetches some quote data from somewhere:
#Singleton
#Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
#PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
The following is the obligatory DAO example:
#Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
#PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
The following shows how declarative security is used, and how a bean looks up something that has been externally mapped into its private context (ENC):
#Stateless
public class TokenFetcher
#Resource
private SessionContext sessionContext;
#RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
The second part of the question seems to be how to use these beans in your code. There are basically four methods:
Injection in managed beans
Bootstrapping via JNDI
Automatically called at startup
Automatically via a timer
Injection is the easiest way, but only managed beans are injection candidates (basically meaning the Java EE framework creates the bean, and you don't use new() to instantiate it).
E.g. Injection:
#ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
#EJB
private InvoiceDAO invoiceDAO;
#PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(also see Communication in JSF 2.0#Processing GET request parameters)
Bootstrapping via JNDI:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
The #Singleton bean showed earlier was an example of how the Java EE framework calls your code itself at startup. For the automatic timer you would use the #Schedule annotation on a bean's method.

Create ApplicationContext as Spring bean (by other application context)

How i can define one ApplicationContext as prototype spring bean in other application context. Also i need pass current context as parent to new application context.
Details:
I have Bean, that represent one user sessions in rich client application. This class manage lifetime of application context, and few other objects (like database connection). This session beans itself configured by special "start-up application context" .
Now i'm want unit test this session beans, but have trouble because session specific application context created inside session bean, and has many depend to "start-up context";
Example code:
public class UserDBAminSession implements ApplicationContextAware, UserSession {
ApplicationContext startupContext;
ApplicationContext sessionContext;
public void setApplicationContext(ApplicationContext startupContext) {...}
public void start() {
createSessionContext() ;
}
private void createSessionContext() {
sessionContext = new ClassPathXmlApplicationContext("admin-session.xml", startupContext);
}
}
For testing purpose i want relapse createSessionContext function code with something like this:
sessionContext = startupContext.getBean("adminContext", ApplicationContext.class);
Then i can create mock of startupContext, what return some stub. Or even DI "session context" to bean by spring, in some future. But, i don't know how pass parent context parameter to ClassPathXmlApplicationContext constructor. I'm try something like this, but it seems not work:
<bean id="adminContext" class="org.springframework.context.support.ClassPathXmlApplicationContext"
scope="prototype" autowire="constructor">
<constructor-arg type="java.lang.String">
<value>admin-session.xml</value>
</constructor-arg>
</bean>
Also I'm think about create application context on top level and pass it by setter, but:
This just move problem to above level, not solve. In fact it already done (UserSession - are this "top level").
This broke RAII pattern.
This need huge code refactoring.
Or make special "context factory" objects, but it harder already not best code.
What look stupid, I can't IoC objects from IoC framework itself. May be i'm misread some spring documentation?
Any other idea, how unit-test this class?
Use FactoryBean and ApplicationContextAware interfaces.
public class ChildApplicationContextFactoryBean implements FactoryBean, ApplicationContextAware {
protected String[] configLocations;
protected ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
#Override
public Object getObject() throws Exception {
return new ClassPathXmlApplicationContext(configLocations, applicationContext);
}
#Override
public Class getObjectType() {
return ClassPathXmlApplicationContext.class;
}
#Override
public boolean isSingleton() {
return true;
}
public void setConfigLocations(String[] configLocations) {
this.configLocations = configLocations;
}
}
Usage:
<bean class="com.skg.ecg.portal.operation.transit.ChildApplicationContextFactoryBean">
<property name="configLocations">
<list>
<value>applicationContext.xml</value>
</list>
</property>
</bean>
If I understand you correctly, your requirement is for managing a collection of beans within a manually-controlled scope (your RIA session, in this case).
Spring has support for scoped beans. You have the basic singleton and prototype scopes, and webapps get the request and session scopes as well. If your RIA session is actually an HTTP session, then I suggest you use session-scoped beans instead of your manually-nested application context design.
If your sessions are not web-related, then you still have the option of definign your own custom scope. There's more work in this, but it is a defined extension point in the container, so you're on safe ground.
Your original idea of application contexts being themselves beans within a parent context would work, yes, but it's probably unnecessary in this case, and just adds complexity. If you want to investigate it further, however, have a look at the SingletonBeanFactoryLocator, which is a Spring infrastructure class for managing hierarchies of application contexts. It won't do the specific job you want, but it might give you ideas.

Categories