Java, how to using expression language in pure java - java

I have a JavaEE web application, as it will be deployed to some kind of application servers such as weblogic websphere tomcat etc. so the EL api will be avaiable for me, but I don't need to care about what EL implementation is used.
I want to use EL in my java code, not jsp pages, to translate some simple expression to value constants, like this:
public static void main(String[] args) {
// TODO Auto-generated method stub
ExpressionFactory ef = new ExpressionFactoryImpl();
SimpleContext ec = new SimpleContext();
ec.setVariable("value", ef.createValueExpression("0", String.class));
ValueExpression ve = ef.createValueExpression(ec, "${value == \"1\" ? \"enabled\" : \"disabled\"}", String.class);
System.out.println(ve.getValue(ec));
}
however, in this example, I used JUEL library, so I need to access JUEL implementation classes. my question is how Can I do the same thing but just use classes in javax.el package ?
Do I need to implement my own ELContext and VariableMapper and other abstract classes ?

I believe you don't need to hack EL together with your code, I think in some cases that might be problemmatic.
There are quite a lot of libraries offering similar functionalities (known as Template Engines), try Velocity or FreeMarker for example. They are extremely easy to use and have quite a lot of options.

MVEL solve my problem, it's flexible and powerful!

Related

WeldContainer and SeContainer

What is the difference between using:
WeldContainer se = new Weld().initialize();
or
SeContainer se = SeContainerInitializer.newInstance().initialize();
I just want to use #Injection and #Produce annotations, but I have not found the difference between these two ways of initializing an object instance.
Context and Dependency Injection (CDI) is a specification. That means it defines an API only and does not provide an implementation. That's why you have to include an implementation such as Weld in order to actually use the API. The WeldContainer class is vendor-specific whereas the SeContainer interface is part of the specification. The former implements the latter.
The SeContainerInitializer class, which is part of the API, will delegate to the implementation included with the application. So if you use Weld as the implementation then ultimately using SeContainerInitializer and SeContainer is the same as using Weld and WeldContainer "under the hood".
From a purist's perspective it's best to rely only on the specification's interface and never directly depend on the implementation. That way you can swap vendors if and when you need to since you're using functionality common to all implementations. However, often times an implementation provides more functionality than what's required by the specification. In order to use that functionality you have to directly depend on the implementation.
In other words, whether you use Weld / WeldContainer or SeContainerInitialializer / SeContainer depends on the (current and future) requirements of your application. When in doubt, program to the interface.
Note this separation between the API and implementation is not unique to CDI. Pretty much the entire Java EE—or as it's now known, Jakarta EE—API works this way. An example would be the Java Persistence API (JPA) and Hibernate or EclipseLink (two implementations). For an example within Java SE there's the Java Database Connectivity (JDBC) API and the various implementations (i.e. drivers).
Using SeContainerInitializer it will load an instance by ServiceLoader.load(...) and initialize it.
public static SeContainerInitializer newInstance() {
return findSeContainerInitializer();
}
private static SeContainerInitializer findSeContainerInitializer() {
SeContainerInitializer result;
Iterator<SeContainerInitializer> iterator = ServiceLoader.load(SeContainerInitializer.class, SeContainerInitializer.class.getClassLoader()).iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException("No valid CDI implementation found");
}
try {
result = iterator.next();
} catch (ServiceConfigurationError e) {
throw new IllegalStateException("Error while instantiating SeContainerInitializer", e);
}
if (iterator.hasNext())
throw new IllegalStateException("Two or more CDI implementations found, only one is supported");
return result;
}
Weld is one implementation of SeContainerInitializer so if it exists on the classpath SeContainerInitializer.newInstance() method will create a new Weld instance and call initialize() method on this object.
Some hints which is a good choice
SeContainerInitializer.newInstance() is a factory method. If you want to create a vendor-independent application it would be good. But Weld is the reference implementation of CDI specification. Honestly I don't think choosing another implementation is necessary.
new Weld().initialize() will create a WeldContainer (which is an implementation of SeContainer). Using this method you will get a vendor-lock but you can use a lot of useful extra features (e.g. add alternatives or interceptors programmatically).
My opinion is: In this case vendor-lock doesn't matter anithing.
Conclusion
If you're planning to change CDI implementation anything else than Weld use independent SeContainerInitializer.newInstance() otherwise just create a Weld instance.
If I were you I would use new Weld() way.

Simple Dependency injection not working

It's the first time I have to use Dependency Injection and I'm a little confused.
I don't really understand how it works.
I have tried on a simple example :
public class StockResponse extends Response
{
#Inject BrandService $brand;
public List<StockResponseItem> stock;
public StockThresholdResponse()
{
stock = new ArrayList<>();
}
public static StockThresholdResponse create(List<DataItem> data)
{
StockResponse stock= new StockResponse();
for (ThresholdCheckAggregate data: d)
{
StockResponseItem item = new StockResponseItem();
item.id = d.thresholdId;
item.brand = str.$brand.byId(d.brand);
str.stockThresholds.add(item);
}
return str;
}
}
But when I use my create() method, I get a null pointer exception for $brand.
I think I have misunderstood how DI works but I can't find my error.
I had similar difficulties to understand how DI (Guice out of Java EE) works. In simple words Guice must have chance to modify You object, for example:
assist by construction usually.
You ask Guice "can You create my object" injector.getInstance(cls), then Guice is creating object for You, solving field or constructor annotation
In normal (non Java EE) environment Yoy never call classic constructor, You ask by second hand.
other method.
Few library / frameworks have integration with Guice (Apache Wicket I personally like) with "creation listeners" on some types of objects. Hard work of DI is hidden for Your eyes, but is executed.
Java EE lets say better EE programmers than me :(
In consequence Yoy don't give chance to inject anything, is null
Professionals sorry that I say at blondie level. That is way like I discovered DI few years ago
Correction to code. Not
StockResponse stock= new StockResponse();
but
mod = .... // Module
injector = Guice.createInjector(mod); // global or almost global
...
injector.getInstance(StockResponse.class);
EDIT: intentionally I don't answer "how to write Guice module", assume this is other, long story
This could work, assuming BrandService is either a concrete class or if it's an interface, you have provided a binding for it to a concrete class elsewhere in your DI configuration (say a module in Guice or Spring #Configuration). I do see one obvious NullPointerException with str variable. Did you mean to do this?
item.brand = stock.$brand.byId(d.brand);

How start with UIMA and simple NLP tasks?

I've recently found out about UIMA (http://uima.apache.org/). It looks promising for simple NLP tasks, such as tokenizing, sentence splitting, part-of-speech tagging etc.
I've managed to get my hands on an already configured minimal java sample that is using OpenNLP components for its pipeline.
The code looks like this:
public void ApplyPipeline() throws IOException, InvalidXMLException,
ResourceInitializationException, AnalysisEngineProcessException {
XMLInputSource in = new XMLInputSource(
"opennlp/OpenNlpTextAnalyzer.xml");
ResourceSpecifier specifier = UIMAFramework.getXMLParser()
.parseResourceSpecifier(in);
AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(specifier);
JCas jcas = ae.newJCas();
jcas.setDocumentText("This is my text.");
ae.process(jcas);
this.doSomethingWithResults(jcas);
jcas.reset();
ae.destroy();
}
private void doSomethingWithResults(JCas jcas) {
AnnotationIndex<Annotation> idx = jcas.getAnnotationIndex();
FSIterator<Annotation> it = idx.iterator();
while (it.hasNext()) {
System.out.println(it.next().toString());
}
}
Excerpt from OpenNlpTextAnalyzer.xml:
<delegateAnalysisEngine key="SentenceDetector">
<import location="SentenceDetector.xml" />
</delegateAnalysisEngine>
<delegateAnalysisEngine key="Tokenizer">
<import location="Tokenizer.xml" />
</delegateAnalysisEngine>
The java code produces output like this:
Token
sofa: _InitialView
begin: 426
end: 435
pos: "NNP"
I'm trying to get the same information from each Annotation object that the toString() method uses. I've already looked into UIMA's source code to understand where the values are coming from. My attempts to retrieve them sort of works, but they aren't smart in any way.
I'm struggling to find easy examples that, extract information out of the JCas objects.
I'm looking for a way to get for instance all Annotations produces by my PosTagger or by the SentenceSplitter for further usage.
I guess
List<Feature> feats = it.next().getType().getFeatures();
is a start to get values, but due to UIMA owns classes for primitive types, even the source code of the toString method in the annotation class reads like a slap in the face.
Where do I find java code that uses basic UIMA stuff and where are good tutorials (except javadoc from the framework itself)?
Generate JCas wrapper classes for your annotation types (you can do this using the type system editor UIMA plugin for Eclipse that comes with UIMA). This will provide you with Java classes that you can use to access the annotations - these offer getters and setters for features.
You should have a look at uimaFIT, which provides a more convenient API including convenience methods to retrieve annotations from the JCas, e.g. select(jcas, Token.class) (where Token.class is one of the classes you generated with the type system editor).
You could find some quick-starting Groovy scripts and a collection of UIMA components on the DKPro Core page.
There is material from the UIMA#GSCL 2013 tutorial (slides and sample code) which might be useful for you. Go here and scroll down to "Tutorial".
Disclosure: I'm developer on UIMA, uimaFIT, DKPro Core and co-organizer on the UIMA#GSCL 2013 workshop.

Tomcat JSP/JSTL without HTTP

I have a pretty standard web app running under Tomcat 7.
What I'm now trying to do is leverage JSP/JSTL as a templating language independent of the HTTP/web serving aspects of Tomcat to produce HTML that can be emailed and converted to PDF.
Has anyone else tried to do this before and could help me with some pointers?
Thanks in advance.
In contrast to what Stephen C said, yes, JSP are Servlets, etc. etc. (And Velocity is quite good and easy to use)
But, what is a Servlet?
It's an interface. An interface with one major method:
service(ServletRequest req, ServletResponse res)
Locate the JSP class, cast it to a Servlet, create implementations of ServletRequest and ServletResponse, and then...
String jspClassName = findJspClassForJSP("your.jsp");
Class jspClass = Class.forName(jspClassName);
Servlet jspServlet = (Servlet)jspClass.newInstance();
MyServletRequest req = new MyServletRequest();
MyServletResponse resp = new MyServletResponse();
jspServlet.init();
jspServlet.service(req, resp);
jspServlet.destroy();
String results = reps.getContent();
Will this work? Well, after some work it will. Obviously you need to implement the minimum facades of the ServletRequest/Response as well as what ever your JSPs will need. But, likely you will probably need little more than the attributes and the streams. If you make your Response return a StringWriter, you're halfway there.
The next part is creating the servlet from the JSP. Handily, the Jasper compiler does that for you -- the game is invoking it. I have never done it directly, but it clearly can be done since both the servlet container does it, as well as the JSPC script/bat file, the ant task, as well as most of the Servlet containers out there use Jasper. So, that can be done. Once you know how to invoke that, you'll know the final generated class name for the JSP. (See the first line of the sample.)
Have I ever done this? No. But I bet within less than a day of messing around you'll know whether this is doable or not. I'm betting it is, especially if you don't run in to any class loader shenanigans. You'll possibly have an issue if you let your users change and regenerate a JSP (so MyEmail.jsp gets compiled in to MyEmail.class, MyEmail_2.class, etc.). But if you invoke Jasper yourself, you'll likely have more control over this.
The other hard part is determining the class name of the JSP. Most of the containers follow a basic pattern here, so if you poke around in the generated code from a WAR you'll likely find it.
Keep the JSPs reasonably simple (and an Email template shouldn't need to super complicated with embedded Java or anything making random calls), and it even more a good chance it will work.
Your solution may not be portable out of the box out of Tomcat, but you likely won't care. The folks that I've talked to that use JSP for templates, simply opened a socket to their own server and made a request. They didn't go this far either.
But on the surface, save some whacky class loader black hole hell, I bet you can get this to work pretty quick. Implement as little of the request and response as you need to, fight a few NPEs as the JSP and JSTL call stuff you weren't planning, and, as Santa says,
Hack away, Hack away, Hack away all!
Addenda:
So, for all the naysayers...
public void runJsp() {
JspC jspc = new JspC();
jspc.setUriroot("/tmp/app");
jspc.setOutputDir("/tmp/dest");
jspc.setJspFiles("newjsp.jsp");
jspc.setCompile(true);
try {
jspc.execute();
Class cls = Class.forName("org.apache.jsp.newjsp_jsp");
Servlet s = (Servlet) cls.newInstance();
MyRequest req = new MyRequest();
MyResponse resp = new MyResponse();
s.init(getServletConfig());
s.service(req, resp);
s.destroy();
System.out.println(resp.getSw().toString());
} catch (JasperException ex) {
throw new RuntimeException(ex);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (ServletException ex) {
throw new RuntimeException(ex);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
Amazing what source code and 1/2 hour in a debugger will do for you.
I created a simple JSP in /tmp/app/newjsp.jsp.
jspc.setUriroot tells the compiler where the base of your "web app" is located. jspc.setOutputDir tells jspc where to put the generated Java and Class files. jspc.setJspFiles tells jspc what files to compile, based off of the URI Root. jspc.setCompile told it to actually compile the code. Finally, jspc.execute() does the deed.
By default Jasper uses the package org.apache.jsp, and creates a new class based on the JSP file name. For my simple experiment, I simply put "/tmp/dest" on to the class path of my Glassfish container, so that the container would find the generated classes.
I load the class, and get an instance.
Finally, I created MyRequest, MyRequest, and, ultimately, MySession. My IDE conveniently created stubs for the respective interfaces. In this case I implemented: MyRequest.getSession(), MyResponse.setContentType(), MyResponse.setBufferSize(), and MyResponse.getWriter().
public PrintWriter getWriter() throws IOException {
if (sw == null) {
sw = new StringWriter();
pw = new PrintWriter(sw);
}
return pw;
}
Obviously sw and pw are instance variables of MyResponse.
MyRequest returned an instance of MySession. My implementation of MySession does -- nothing. But the runtime wanted a Session, it just doesn't use it on its own for my very simple JSP, and I wasn't motivated on stuffing in the the one from the Servlet.
I tested this on Glassfish v2.1. I simply added appserv_rt.jar (from glassfish/lib) to my build class path (so it could find the JspC jars), but I don't bundle it in the WAR (since it's already in the container).
And, shazam, it worked. In "real life", assuming the process that wanted to leverage the JSP was actually sourced from a web request, I would simply create an HttpServletResponseWrapper and override the earlier three methods, the rest would probably Just Work. If a web request isn't in the picture at all, then you'd need to create your own Session implementation (no big deal really, it's just a map).
I'd also use a private URLClassLoader to load the faux JSP classes. If I KNEW I'd never reload a JSP, then would just make the destination my WEB-INF/classes directory and give it it's own package and let the system load them.
But, yup, it worked. No big deal. It's just java.
This doesn't really make sense. A JSP is some nice syntax that results in the generation of a Java EE servlet class. Indeed, the "servlet" / "http" nature of a JSP is thoroughly intertwined through the APIs and the semantic model of JSPs and JSTL.
If you want to generate HTML independently of web requests, you would be better of using a different templating technology; e.g. Velocity or FreeMarker. If you then want the HTML to be delivered as web responses as well, arrange that your servlets call the templating engine to generate responses. (If you are using Spring there is existing infrastructure for this. Other frameworks may have similar support, but if not, it shouldn't be hard to implement some glue code yourself to do this.)

Methods for getting annotation metadata in Java

I'm working on a JSR-303 validation framework for GWT. Some of you may have heard of it even though it is a small project. Here is gwt-validation.
In the old days (v1.0) it used a marker interface for each class and each class had metadata generated separately. This was bad because it was not part of the JSR-303 standard and we moved on to the next idea.
In version 2.0 it scans the classpath at runtime using Reflections. This is great. The downside is that it doesn't seem to be able to work inside of containerized environments or those with special restrictions.
This is probably my fault, look at the following code:
//this little snippet goes through the classpath urls and ommits jars that are on the forbidden list.
//this is intended to remove jars from the classpath that we know are not ones that will contain patterns
Set<URL> classPathUrls = ClasspathHelper.forJavaClassPath();
Set<URL> useableUrls = new HashSet<URL>();
for(URL url : classPathUrls) {
boolean use = true;
for(String jar : this.doNotScanJarsInThisList) {
if(url.toString().contains(jar)) {
use = false;
break;
}
}
if(use) {
useableUrls.add(url);
}
use = false;
}
ConfigurationBuilder builder = new ConfigurationBuilder()
.setUrls(useableUrls)
.setScanners( new TypeAnnotationsScanner(),
new FieldAnnotationsScanner(),
new MethodAnnotationsScanner(),
new SubTypesScanner()
)
.useParallelExecutor()
;
this.reflections = new Reflections(builder);
I'm using the filter to remove jars that I know can't have annotations in them that I'm interested in. As I mention this gives a huge speed boost (especially on large classpaths) but the ClasspathHelper.forJavaClassPath() that I'm basing this on probably isn't the best way to go in container environments. (e.g. Tomcat, JBoss)
Is there a better way or at least a way that will work with a container environment and still let my users filter out classes they don't want?
I've looked, some, into how the Hibernate Validation project (the reference implementation for JSR-303) and they appear to at least be using (at least in part) the Annotations Processing in Java 6. This can't be all of the story because that didn't show up until JDK6 and Hibernate Validator is JDK5 compatible. (See: hibernate documentation)
So, as always, there's more to the story.
I've read these threads, for reference:
About Scannotation which has been pretty much replaced by Reflections.
This one but it uses File and I'm not sure what the implications are of that in things like GAE (Google App Engine) or Tomcat.
Another that goes over a lot of the things I've talked about already.
These threads have only helped so much.
I've also read about the annotation processing framework and I must be missing something. It appears to do what I want but then again it appears to only work at compile time which I know isn't what is done by Hibernate Validator. (Can anyone explain how it does scanning? It works on GAE which means it can't use any of the IO packages.)
Further, would this code work better than what I have above?
Set<URL> classPathUrls = ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader());
Could that correctly get the classloader inside of a Tomcat or JBoss container? It seems scan a smaller set of classes and still finish okay.
So, in any case, can anyone help me get pointed in the right direction? Or am I just stuck with what I've got?
You could take a look at Spring's annotation support.
Spring can scan annotations in files (using asm IIRC), and works in and out of a container.
It may not be easy because it goes through Spring's Resource abstraction, but it should be doable to reuse (or extract) the relevant code.

Categories

Resources