As I’m often looking for the correct header of the beans.xml file required for Web Beans / Context and Dependency Injection (CDI) to work, I decided to share this simple header here with you.
If you don’t have anything to declare, create an empty beans.xml like this one
If you have to declare alternatives or interceptors, do it like this
com.dominikdorn.dc.passwordReset.PasswordResetService
com.dominikdorn.dc.passwordReset.StudyGuruPasswordReset
A good IDE will help you with creating a proper beans.xml as soon as you specify the xml namespace.
Popular implementations of CDI are
I just got my StarCraft 2 Collectors Edition.
Right after unpacking it, I inserted the DVD and was wondering “They ship a whole DVD with just 2 Files, not more than 3 MB of size?”
The thing is: The DVD has a file system called UDF which supports hidden files and directories. Unlike with normal filesystems in linux, even a ls -lah does not show these files.
1. Unmount the DVD
Make sure to unmount the DVD first.
Close every filemanager and console that has the DVD folder open.
In my Ubuntu installation, the DVD is mounted to /media/cdrom0
Do the following in a console
sudo umount -f /media/cdrom0
If it does not work, look which processes still have a lock on the directory using
sudo lsof /media/cdrom0
and kill those.
2. Mount the DVD correctly
First, get your own user Id. Most of the times its just 1000.
id
should return something like this
uid=1000(domdorn) gid=1000(domdorn) groups=4(adm),20(dialout),24(cdrom),46(plugdev),103(fuse),104(lpadmin),114(admin),118(sambashare),1000(domdorn)
Note the values of uid=… and gid=…. (here both are 1000)
Next, mount the DVD the following way:
mount /dev/cdrom /media/cdrom0 -o uid=1000,gid=1000,unhide,umask=0000
unhide makes linux show the hidden files on the dvd, uid/gid makes sure you’re allowed to read the files.
3. Start the Installer
Now try to start the installer: Open a console, change to /media/cdrom0 and start it.
cd /media/cdrom0
wine Installer.exe
If you’re lucky, it now works out of the box and you are finished.
If not (like me), it simply does nothing and we have to do the following.
4. Copy the DVD
If the Installer does not work out of the box, create a folder on your filesystem, e.g.
~/.wine/drive_c/sc2install
and copy the whole DVDs contents to this directory. After this is finished, try to start the Installer from there.
Log into your Battle.net Account.
http://www.battle.net
and Add your CD-Key to your Account. If you don’t have an Battle.net Account yet, create one, you’ll need it anyway.
After you’ve added the Game to your account, download the Windows Installer.
Start up the downloaded installer and select a folder in your wines Drive C. Let it download a few bytes and then quit the installer.
Now copy the files
Installer Tome 1.MPQE.part Installer UI 1.MPQ.part Installer UI 2.MPQE.part
from /media/cdrom0 to the created folder. In my case its ~/.wine/drive_c/sc2download/SC2-WingsOfLiberty-enGB-Installer
Now startup the downloaded installer again.
It should start checking the downloaded files (you might not see a difference in the progress bar, but the CPU goes up, watch with “top”).
After the file check is finished, the installer should start.
For a project at the university, I had to implement an abstract search in an abstract JPA Dao.
Maybe this class comes handy for some of you
package com.dominikdorn.rest.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author Dominik Dorn
*/
public class AbstractJpaDao {
@PersistenceContext
protected EntityManager em;
protected Class entityClass;
public Class getEntityClass() {
return entityClass;
}
public void setEntityClass(Class entityClass) {
this.entityClass = entityClass;
}
public AbstractJpaDao() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
this.entityClass = (Class) genericSuperclass.getActualTypeArguments()[0];
}
public AbstractJpaDao(Class clazz) {
this.entityClass = clazz;
}
public EntityManager getEm() {
return em;
}
public AbstractJpaDao setEm(EntityManager em) {
this.em = em;
return this;
}
@Override
public TYPE persist(TYPE item) {
if (item == null)
throw new PersistenceException("Item may not be null");
em.persist(item);
return item;
}
@Override
public TYPE update(TYPE item) {
if (item == null)
throw new PersistenceException("Item may not be null");
em.merge(item);
return item;
}
@Override
public List getAll() {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return em.createQuery(cq).getResultList();
}
@Override
public TYPE getById(Long id) {
if (id == null || id < 1)
throw new PersistenceException("Id may not be null or negative");
return (TYPE) em.find(entityClass, id);
}
@Override
public void delete(TYPE item) {
if (item == null)
throw new PersistenceException("Item may not be null");
em.remove(em.merge(item));
}
@Override
public List findByAttributes(Map attributes) {
List results;
//set up the Criteria query
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(getEntityClass());
Root foo = cq.from(getEntityClass());
List predicates = new ArrayList();
for(String s : attributes.keySet())
{
if(foo.get(s) != null){
predicates.add(cb.like((Expression) foo.get(s), "%" + attributes.get(s) + "%" ));
}
}
cq.where(predicates.toArray(new Predicate[]{}));
TypedQuery q = em.createQuery(cq);
results = q.getResultList();
return results;
}
}
To instantiate this for an Entity, e.g. “Item”, simply do this
// get an entityManager somewhere here
AbstractJpaDao- dao = new AbstractJpaDao
- ();
dao.setEm(em);
now you can use this Data Access Object for your persistence stuff.
To now search for entities in your DB, you can use the method findByAttributes which takes a map<String,String> and searches for appropriate items.
If your Entity looks like this
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "ITEM_GEN")
@SequenceGenerator(name="ITEM_GEN", allocationSize=25, sequenceName = "item_seq")
private long id;
@Basic
private String name;
@Basic
private String description;
@Basic
private Integer size;
// constructors, getters, setters
you could search for an item which names contain “test” like this
Map attr = new Hashmap();
attr.put("name", "test");
List- results = dao.findByAttributes(attr);
which comes quite handy in my opinion. Also note, that you don’t have to pre-generate your JPA2 Model classes.
In my time on the Glassfish users mailinglist, I came across some important links for everyone setting up a Glassfish server for production.
This is my personal bookmarks list, that may also serve its purpose to others.
This post will be updated with new additional & helpful links, as soon as I get aware of them.
Do you have interesting links? Post them in the comments!
If you are integrating a PHP Application in your Java Environment, you’ll probably came across Quercus, a Java Implementation of PHP provided by Caucho Technologies.
As you are moving more and more into the Servlet world, you’ll probably will be using Servlet-Filters and normal Servlets todo some tasks.
If you then want to access Variables in a PHP Session, here’s how to do it:
The Quercus PHP-Session is not stored the same way as the normal Servlet HTTP-Session is stored. Quercus uses an own Session Manager that is capable of doing all this stuff that you know from PHP, like e.g. migrating Session-IDs (to prevent session-hijacking etc.).
To access this Session Manager, you first have to get a hand on the QuercusContext. In the current release (4.0.7) there is no easy way to get a hand on it if you are not inside a PHPModule or a PHP-Page. Thus I simply copied com.caucho.quercus.servlet.QuercusServlet to com.caucho.quercus.servlet.DCQuercusServlet and added this line to the end of the method:
private void initImpl(ServletConfig config)
throws ServletException
{
....
config.getServletContext().setAttribute("quercusContext", quercus);
}
which exposes the QuercusContext as an Attribute in the ServletContext.
(Note: If you are running multiple QuercusServlets in your WebApp – which you probably shouldn’t – this might will be a problem)
(Note2: The package name com.caucho.quercus.servlet must be used, or else you will not have access to some package scoped properties used in the QuercusServlet)
Ok, so now we have access to the QuercusContext from every Servlet, Filter or JSF-Bean, horray
But how to use it?
Lets take a look at the following filter and its methods helping me to work with the PHP-Session:
public class LoginOutFilter implements Filter {
QuercusContext context; // we store the reference to the quercusContext in the filter
FilterConfig config; // the reference to the config
...
@Override
public void init(FilterConfig filterConfig) throws ServletException {
config = filterConfig;
}
// looks up the QuercusContext the first time it is accessed
// Beware: will return null if no PHP page has been rendered yet and the quercusContext is not already set.
private QuercusContext getQuercusContext()
{
if(context == null)
{
context = (QuercusContext) config.getServletContext().getAttribute("quercusContext");
}
return context;
}
// find the PHP-Session Cookie in the array of Cookies provided by the browser
public Cookie findPHPSessionCookie(Cookie[] cookies)
{
for(Cookie c : cookies)
{
if(c.getName().equals("PHPSESSID")){
return c;
}
}
return null;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if(someCondition)
{
// clear a PHP-Session, e.g. when logging out a user
Cookie c = findPHPSessionCookie(((HttpServletRequest) servletRequest).getCookies());
if(c != null){
QuercusSessionManager mng = getQuercusContext().getQuercusSessionManager();
String phpSessionId = c.getValue();
mng.removeSession(phpSessionId);
}
}
if(someOtherCondition) {
QuercusSessionManager mng = getQuercusContext().getQuercusSessionManager();
SessionArrayValue val;
Cookie c = findPHPSessionCookie(((HttpServletRequest) servletRequest).getCookies());
String phpSessionId;
if(c != null)
{
// we found a session cookie
phpSessionId = c.getValue();
val = mng.getSession(null, phpSessionId, new Date().getTime() );
if(val == null)
{
// but the session does not exist on the server, so create it
val = mng.createSession(null, phpSessionId, new Date().getTime());
}
}else
{
// we haven't found a php-session cookie, so create a new session
val = mng.createSession(null,null,new Date().getTime());
phpSessionId = val.getId();
// and store the appropriate cookie
Cookie newCookie = new Cookie("PHPSESSID", phpSessionId);
((HttpServletResponse)servletResponse).addCookie(newCookie);
}
// storing data in the session
String username = "myUsername";
val.put("ludata_suserid", username);
val.put("ludata_nusernr", someService.getUserId(username));
val.put("ludata_nstatusnr", someService.getUserStatus(username));
val.addUse(); // This is required for saving, else an IllegalStateException will be thrown
mng.saveSession(null, val);
}
}
The above code shows how to erase a session and how to add values to a session. To get values from a session, simply use val.get(..).
Attention: This currently only works if the page after the filter is not a Quercus Page itself (e.g. a Servlet or a JSF Page). I’m working on a solution for this
Once in a while one stumbles upon an error message like this
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/mail/Session
This happens if your code compiles against incomplete classes, like the JavaEE6 Api and your Unit tests try to access code thats not there. JUnit will simply fail and mark the test as error, printing something like this
Tests in error: initializationError(com.dominikdorn.dc.passwordReset.SimplePasswordResetServiceTest)
and the corresponding surefire text file starts like this:
-------------------------------------------------------------------------------
Test set: com.dominikdorn.dc.passwordReset.SimplePasswordResetServiceTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.022 sec <<< FAILURE!
initializationError(com.dominikdorn.dc.passwordReset.SimplePasswordResetServiceTest) Time elapsed: 0.005 sec <<< ERROR!
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/mail/Session
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
....
The Solution
You have to compile against real-implementations of the classes. You do that by adding those dependencies before the most generic dependency in your pom.xml
As example, we add javax.mail BEFORE javaee6-api like this
...
javax.mail
mail
1.4
provided
javax
javaee-api
6.0
provided
If you are deploying your App on an Appserver like Glassfish or JBoss AS, leave the scope of javax.mail:mail as provided to prevent the inclusion of the jar in the final webapp.
I now list required dependencies for various Absent Code Errors I've encountered and still encountering. This post will be updated every time I solve another of these problems.
JavaMail: javax/mail/Session
...
javax.mail
mail
1.4
provided
Servlet 3.0
...
org.glassfish
javax.servlet
3.0
provided
...
....
Glassfish
Glassfish Maven2 Repository
http://download.java.net/maven/glassfish/
JPA2: javax/persistence/PersistenceException
...
org.eclipse.persistence
javax.persistence
2.0.0
provided
...
..
...
...
eclipse
Eclipse Maven Repository
http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo
JAX-RS: javax/ws/rs/core/UriBuilder
com.sun.jersey
jersey-core
1.1.5
provided
com.sun.jersey
jersey-json
1.1.5
provided
com.sun.jersey
jersey-test-framework
1.1.5.1
test
more to come soon!
In XHTML strict, the ol-tag does not have the attribute start.
To get this working again, simply create a css-class
.counterList li {display: block }
.counterList li:before {content: counter(start) ". "; counter-increment: start}
and surround your list with a tag like this
import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.inject.Inject;
@FacesConverter(forClass = AvailableCountry.class)
@ManagedBean // does not help
@RequestScoped // does not help
public class AvailableCountryConverter implements Converter
{
@Inject
AvailableCountryDao dao;
@PostConstruct
public void postConstruct()
{
System.out.println("calling postConstruct");
}
public Object getAsObject(FacesContext facesContext, UIComponent
component, String value) {
if (value == null || value.length() == 0) {
return null;
}
return dao.find(getKey(value));
}
Long getKey(String value) {
Long key;
key = Long.valueOf(value);
return key;
}
String getStringKey(long value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent
component, Object object) {
if (object == null) {
return null;
}
if (object instanceof AvailableCountry) {
AvailableCountry o = (AvailableCountry) object;
return getStringKey(o.getCountry().getId());
} else {
throw new IllegalArgumentException("object " + object + "
is of type " + object.getClass().getName() + "; expected type: " +
AvailableCountry.class.getName());
}
}
}
But my DAO was not injected, nor was the postConstruct method triggered by CDI.
Why?
Because the bean is not managed by CDI, not even when annotating it with @ManagedBean because it gets created by the JSF-Lifecycle and not by CDI.
Well.. but how to manually lookup a Bean with CDI / Weld?
First, you need to get the BeanManager. When you have a FacesContext (like in the converter above), you can get it like this:
public BeanManager getBeanManager()
{
return (BeanManager)
((ServletContext) facesContext.getExternalContext().getContext())
.getAttribute("javax.enterprise.inject.spi.BeanManager");
}
If you don’t have access to a FacesContext, ServletContext or similar, you can lookup the BeanManager through JNDI
public BeanManager getBeanManager()
{
try{
InitialContext initialContext = new InitialContext();
return (BeanManager) initialContext.lookup("java:comp/BeanManager");
catch (NamingException e) {
log.error("Couldn't get BeanManager through JNDI");
return null;
}
}
After you’ve got your BeanManager, simply lookup your Bean like this:
(In my case, I wanted to lookup a bean with the type AvailableCountryDao)
Type-based CDI manual lookup
public AvailableCountryDao getFacade()
{
BeanManager bm = getBeanManager();
Bean bean = (Bean) bm.getBeans(AvailableCountryDao.class).iterator().next();
CreationalContext ctx = bm.createCreationalContext(bean);
AvailableCountryDao dao = (AvailableCountryDao) bm.getReference(bean, AvailableCountryDao.class, ctx); // this could be inlined, but intentionally left this way
return dao;
}
Thanks to my friend Lincoln Baxter, III for the snipped.
Name-based CDI manual lookup
public Object getBeanByName(String name) // eg. name=availableCountryDao
{
BeanManager bm = getBeanManager();
Bean bean = bm.getBeans(name).iterator().next();
CreationalContext ctx = bm.createCreationalContext(bean); // could be inlined below
Object o = bm.getReference(bean, bean.getClass(), ctx); // could be inlined with return
return o;
}
So, now you’re able to manually lookup beans with CDI.
In case you have the same problem (with Converters/Validators) like I had above, checkout Seam Faces, where this problem already is fixed,
meaning your @ManagedBean annotated Converter/Validator is working as expected with @Inject, @PostConstruct & @PreDestroy
If you – like me – have the problem, that you need to run Tomcat or Glassfish or any other Java Webserver on Port 80, this might come handy for you:
The problem:
Tomcat, Jetty, Glassfish, JBoss AS etc. .. they all run on unprivileged ports > 1024, defaulting to 8080.
If you want to run them on port 80, you have several choices:
- front them with Apache
- front them with Squid
- use some tools like authbind, etc.
- use IPTables magic (which we will describe here)
Primitive IPTables solution:
This solution comes from the blog entry ” Installing Tomcat on port 80 with iptables ”
You have to compile NAT support into your kernel and use an iptables rule like this one
iptables -t nat -I PREROUTING --src 0/0 --dst $yourip -p tcp --dport 80 -j REDIRECT --to-ports 8080
which redirects all incoming traffic on port 80 on $yourip (e.g. 74.125.39.99) to port 8080 on the local machine.
If your webserver listens only to 127.0.0.1 this is all you need to be save.
However, I have a bit a different setup:
- Two networks with different providers (4mbit e.g. 74.125.39.99, 12mbit e.g. 98.137.149.56 )
- Two servers, one of them quite small powered (pentium4 on the 4mbit line), the other quite strong (dual quad core 2ghz on the 12mbit line)
- Glassfish on the strong server
- DNS load balancing for the domain
- both servers should map to the same glassfish instance.
- the servers are connected through a direct link with private IP-addresses (10.x.x.x range)
- Glassfish binds only to the private IP-Address of the strong server, meaning 10.0.100.10:8080
- both 74.125.39.99:80 and 98.137.149.56:80 should redirect the traffic to 10.0.100.10:8080
Here’s how I’ve done it (I got some inspiration from this linux questions forum entry):
On the “strong” server
#this forwards traffic to the internal ip
iptables -A PREROUTING -t nat -d 74.125.39.99/32 -p tcp -m tcp --dport 80 -j DNAT --to 10.0.100.10:8080
#this allows traffic on the external interface on port 80
iptables -A INPUT -d 74.125.39.99/32 -p tcp -m tcp --dport 80 -j ACCEPT
#this allows traffic on the internal ip on port 8080
iptables -A INPUT -d 10.0.100.10/32 -p tcp -m tcp --dport 8080 -j ACCEPT
nearly the same on the “weaker” server
#this forwards traffic to the internal ip
iptables -A PREROUTING -t nat -d 74.125.39.99/32 -p tcp -m tcp --dport 80 -j DNAT --to 10.0.100.10:8080
#this allows traffic on the external interface on port 80
iptables -A INPUT -d 98.137.149.56/32 -p tcp -m tcp --dport 80 -j ACCEPT
That’s it!
Perfectly save, perfectly scalable glassfish v3 (no apache bottleneck in your comet apps!)
As I sometimes need these, I have compiled a list of the valid headers of the web.xml and web-fragment.xml file for servlet version 2.3 until 3.0.
Maybe you find them as handy as I do.
web.xml v2.3
web.xml v2.4
web.xml v2.5
web.xml v3.0
web-fragment.xml: