I just noticed today that github has changed the way it's pull requests work, so it is now possible to merge pull requests using:
git pull --rebase upstream pull/$no/head
(where $no is the pull request number)
I wrote a simple function that takes pull request numbers as parameters that I thought I would share in the hope it would make life easier for anyone who has to merge a lot of pull requests.
pull() { cmd="git fetch upstream " for var in "$@" do cmd="$cmd pull/$var/head:pullRequest$var" done $cmd for var in "$@" do git checkout pullRequest$var git rebase master git checkout master git merge pullRequest$var git branch -D pullRequest$var done }
After putting this in your bashrc file you can use it as follows:
pull 251 252 253
This will fetch all the pull requests into temporary branches, check them out, rebase them and then merge them into master.
I am going to be speaking about JBoss Application Server 7 at the Sydney JBoss Users Group this Thursday 21st. If you are in Sydney and want to find out more about AS7, feel free to drop in. There should be pizza and beer after the talk.
Full details are here: http://app.engage.redhat.com/e/es.aspx?s=1795&e=47233&elq=c01d4c1ee2ef430880d2807d84f610b0
Update: I originally posted the date as Wednesday 20th, I forgot that the date has actually changed to Thursday 21st.
Seam XML configuration Beta1 has been released. You can start using it with the following pom.xml declaration:
<dependency> <groupId>org.jboss.seam.xml</groupId> <artifactId>seam-xml-config</artifactId> <version>3.0.0.Beta1</version> </dependency>
This release does not have many significant changes since the Alpha3 release (mainly documentation and example fixes).
As Weld Extensions has been renamed Seam Solder this is the last release that will use Weld Extensions, future releases will use Seam Solder.
[Project Page] - [Download] - [Documentation]
Seam Persistence Beta 1 has been released. To get started put the following in your pom.xml:
<dependency> <groupId>org.jboss.seam.persistence</groupId> <artifactId>seam-persistence-impl</artifactId> <version>3.0.0.Beta1</version> </dependency> <dependency> <groupId>org.jboss.weld</groupId> <artifactId>weld-extensions</artifactId> <version>1.0.0.Beta1</version> </dependency>
The release adds support for Seam managed Hibernate sessions, and fixes a bug where the SMPC would not join a transaction correctly if used outside a transaction.
Seam managed hibernate sessions are configured via producer methods:
@RequestScoped @Produces @SeamManaged public SessionFactory createSessionFactory() { Configuration config = new Configuration(); config.configure(); return config.buildSessionFactory(); }
This declaration results in the creation of two beans, an application scoped SessionFactory and a @RequestScoped Session.
This Session can be injected as follows:
@Inject Session session;
This managed session will automatically join the active transaction, and allows the use of EL in queries:
Hotel hilton = (Hotel) session.createQuery("select h from Hotel h where h.name=#{hotelName}").uniqueResult();
This is the last release of Seam Persistence that will use Weld Extensions. Weld Extensions has been renamed to Seam Solder, and future release will require Solder instead.
Key Links:
We are pleased to announce the availability of Seam XML Configuration 3.0.0.Alpha3 and Seam Persistence 3.0.0.Alpha1.
Seam Persistence
Seam Persistence brings transactions to managed beans, and also provides the Seam Managed Persistence Context, a conversation scoped extended persistence context for use in CDI based applications. Currently it provides the following features
In keeping with the spirit of he Seam Managed persistence context is configured via annotations:
@Produces @ConversationScoped @SeamManaged @PersistenceUnit(unitName="myPu") EntityManagerFactory factory;
The SMPC can then be injected directly into your managed beans:
@Inject EntityManager em;
For more information check out the getting started guide.
[Download] [JIRA] [Reference Guide] [Project Page]
Seam XML Config
Seam XML Configuration allows you to configure CDI beans using XML, this release is mainly a compatibility and bugfix release, however there are some notable changes.
Seam XML now supports the concept of XML configured virtual producer fields. These fields can be used to configure primitive types and Java EE resources via XML:
<s:EntityManager> <s:Produces/> <sPersistenceContext unitName="customerPu" /> </s:EntityManager> <s:String> <s:Produces/> <my:VersionQualifier /> <value>Version 1.23</value> </s:String>
This is equivilent to the following java:
class SomeClass { @Produces @PersistenceContext(unitName="customerPu") EntityManager field1; @Produces @VersionQualifier String field2 = "Version 1.23"; }
Using virtual producer fields it is also possible to configure the Seam Managed Persistence Context via XML.
The other notable change is that generic beans have been removed, as these are now provided as part of Weld Extensions.
[Download] [JIRA] [Reference Guide] [Project Page]
This is a post about how Weld uses proxies, and some of the non-portable enhancements that weld includes to allow the proxying of classes that would not normally be proxiable.
In Seam 2 injection was performed dynamically via an interceptor. Every time a method was invoked on a Seam component the BijectionInterceptor would look up a value for each injection point on the component and inject it. When the invocation was complete the interceptor would then set the fields back to null, to prevent the component from hanging onto shorter lived components that would otherwise have been eligible for garbage collection. This approach works quite well, however it has two main problems:
- Performance
The bijection process is not particularly fast. If you were making repeated invocations on a component (from a <h:DataTable> for example) you would experience performance problems. The solution was to use @BypassInterceptors and not use dependency injection in methods that experienced performance problems.
- Thread Safety
If an unsynchronized application scoped component tried to inject a component with a narrower scope (e.g. a session scoped component) thread safety problems would occur. If two threads made calls to the component at the same time the second thread could end up accessing components from the first threads session. This could result in problems that only appear when the application is under load.
The CDI Approach To Dependency Injection
CDI uses a different approach to dependency injection. Instead of using interceptors, injection is performed once at bean creation time. Dependent scoped beans can be injected directly, as the dependent beans lifecycle is tied to the bean it is injected into.
For normal scoped beans however this approach will not work, as the lifecycles of the beans are different, so instead weld injects a proxy. A proxy is a subclass of the bean that is generated at runtime. This proxy overrides all the non-private methods of the bean class, when these overridden methods are invoked the proxy looks up the correct instance of the bean and then forwards the invocation onto the actual bean instance. Say for example we have the following:
@ConversationScoped class PaymentProcessor { public void processPayment(int amount) { System.out.println("I'm taking $" + amount); } } @ApplicationScoped public class Shop { @Inject PaymentProcessor paymentProcessor; public void buyStuff() { paymentProcessor.processPayment(100); } }
In this situation the PaymentProcessor instance is not injected directly into Shop. Instead a proxy is injected, and when the processPayment() method is called the proxy looks up the current PaymentProcessor bean instance and calls the processPayment() method on it. Conceptually, this would look sort or like this:
public class PaymentProcessor_$$Proxy extends PaymentProcessor { public void processPayment(int amount) { PaymentProcessor instance = lookupBean(); instance.processPayment(amount); } private PaymentProcessor lookupBean() { //get the correct instance from the BeanManager and return it } }
This has several advantages over the seam 2 dynamic injection approach:
- No interceptors are required
In many situations this will be a big performance win.
- Proxies are thread safe
The proxy will always forward the invocation to the correct bean instance, even when multiple threads are accessing a bean at the same time.
- Bean lookup only happens when invoking a method on the bean
In seam 2 even if a method did not use an injected object, it was still created and injected. In CDI a bean will only be created when it is actually used.
With that said, there are some things you need to be aware of:
- When the proxy is created the bean constructor is called
This is because constructors always have to call the superclass constructor (well, mostly). As the proxy is a sub class of the bean, the bean constructor is invoked when the proxy is created. When using CDI instead of doing bean initialisation in the constructor, you should do it in a @PostConstruct method.
- Not all classes can be proxied
The CDI spec places some limits on which beans can be proxied, mainly due to technical restrictions in the JVM.
- You need to be carful implementing equals() for normal scoped beans
Classes that implement equals by comparing fields directly in the equals() method may not work as expected, as the class will be inspecting the fields of the proxy, and not the bean instance.
Which Classes can be proxied?
The CDI specification places the following limitation on normal scoped beans:
Primitive types and array types cannot be proxied because they cannot be subclassed, and neither can classes which are declared final. Classes with final methods are also not allowed, as the final methods cannot be overridden to forward calls to the correct bean instance. These limitations are strictly enforced by the JVM, short of instrumenting classes as they are loaded to remove the final modifier, there is no way around them.
The constructor limitation is a bit less obvious. The JVM requires that all constructors either call another constructor on the current class or a constructor on the superclass. The means that the proxy subclass must call a bean constructor, and the only one one that makes sense is the default constructor. Although theoretically we could call a non-private constructor with made up arguments (such as nulls and zero's), there is a high chance that this will result in problems such as NullPointerExceptions, so for safety's sake the specification disallows it. This is where Weld's unsafe proxies extension comes into the picture.
Weld's Unsafe Proxies Extension
All JVM's provide a method of creating a class without calling the constructor. This is necessary for the serialisation API, which needs to create class instances without calling the constructor during the de-serialisation process. Weld can use these API's on some common JVM's in order to relax the constructor restrictions on normal scoped beans. This is enabled by putting an empty file
META-INF/org.jboss.weld.enableUnsafeProxies
somewhere on the applications classpath. Internally this uses the sun.misc.Unsafe class, so at the moment it is only availible on JVM's where this class is available. This may be extended to work on other JVM's in future.
Using this extension means that normal scoped beans no longer require a default constructor. Proxies instances are created directly, and the bean constructor is never called. This functionality is currently available in the latest release of weld (1.1 Beta1).
The beans will still require a non-private constructor of some kind. This is due to another JVM restriction, that requires all constructors to call either a superclass constructor or another constructor on the current class. If all the constructors of a class are private then it is impossible to call super(). It it however possible to get around this restriction by generating some bytecode that when expressed in java would look like this:
public class MyClass { public MyClass(int a) { this(""); } public MyClass(String a) { this(0); } }
This is not valid java code, as the compiler will complain about the recursive initialisation. This is a java language restriction however, if we generate the corresponding bytecode directly using a library such as javassist we can then load this directly into the JVM.
Attempting to instantiate this class normally would result in a stack overflow, however we can use com.sun.Unsafe to bypass the constructor call altogether and create an instance of the proxy class. This functionality is currently only available when building from the latest sources.
Using these techniques it is possible to bypass all the constructor based limitations on normal scoped beans, albeit not in a very portable way.
With an app that I worked on recently it was decided that links the user did not have permission to view would show up as disabled. There was quite a lot of links in the application, and I am pretty lazy, so I decided to have a look and see if there was a better way of doing this than having to edit the disabled property of all the links. As it turns out there is using a facelets TagDecorator (this is now part of JSF 2).
A TagDecorator allows you to modify a tag on your page before the page is compiled, I decided to use it to automatically add an el based 'disabled' property to all my s:link and s:button controls:
public class SecurityTagDecorator implements TagDecorator { public Tag decorate(Tag tag) { if (!tag.getNamespace().equals("http://jboss.com/products/seam/taglib")) { return null; } //we are only interested in s:link and s:button if (tag.getLocalName().equals("link") || tag.getLocalName().equals("button")) { TagAttribute view = tag.getAttributes().get("view"); if (view == null) { return null; } String viewId = view.getValue(); //don't try and fix el based permission if (viewId.contains("#{")) { return null; } //el expression that tests if a page is viewable String disabled = "#{not pageSecurityManager.isViewable('" + viewId + "')}"; //we also add the permissionDenied styleClass to the link String styleClass = "#{pageSecurityManager.isViewable('" + viewId + "') ? '' : ' permissionDenied'}"; TagAttribute[] at = tag.getAttributes().getAll(); boolean styleFound = false; boolean disFound = false; //loop through all the attributes on the tag. We need to make sure there is //not an existing diabled or styleClass tag. //if there is we replace it for (int j = 0; j < at.length; ++j) { TagAttribute i = at[j]; if (i.getLocalName().equals("styleClass")) { styleFound = true; String val = i.getValue(); //add our style el expression to the existing attribute TagAttribute ti = new TagAttribute(i.getLocation(), i .getNamespace(), i.getLocalName(), i.getQName(), val + styleClass); at[j] = ti; } if (i.getLocalName().equals("disabled")) { disFound = true; //replace the disabled attribute TagAttribute ti = new TagAttribute(i.getLocation(), i .getNamespace(), i.getLocalName(), i.getQName(), disabled); at[j] = ti; } } //if the attributes were not found we add new ones if (!styleFound) { TagAttribute ti = new TagAttribute(tag.getLocation(), "", "styleClass", "styleClass", styleClass); TagAttribute[] old = at; at = new TagAttribute[old.length + 1]; for (int k = 0; k < old.length; ++k) { at[k] = old[k]; } at[old.length] = ti; } if (!disFound) { TagAttribute ti = new TagAttribute(tag.getLocation(), "", "disabled", "disabled", disabled); TagAttribute[] old = at; at = new TagAttribute[old.length + 1]; for (int k = 0; k < old.length; ++k) { at[k] = old[k]; } at[old.length] = ti; } //return our modified tag TagAttributes ats = new TagAttributes(at); return new Tag(tag, ats); } return null; } }
We then need to register our TagDecorator in web.xml:
<context-param> <param-name>facelets.DECORATORS</param-name> <param-value> com.mydomain.SecurityTagDecorator; </param-value> </context-param>
And vola, all the s:links in the application are automatically disabled if the user does not have permission to use them.
In my spare time I have been working on fakereplace, a project that aims to provide more fine grained hot deployment in java that what is currently availible.
Currently hot deployment of code changes is done one of two ways, either by discarding the applications ClassLoader(s) and reloading the application, or by using JVM HotSwap.
Discarding the ClassLoader and then re-loading all application classes works quite well for small projects, however for large applications it is often not as effective. For bigger projects the time spent initialising the application is often much greater than the amount of time the application server takes to load, so the time saving is quite small. Discarding the old application can also result in significant garbage collection overhead, so in some cases a hot deployment can actually be slower than an application server restart.
HotSwap on the other hand works pretty much instantly, however it is quite limited in the changes it can make. It does not allow changes to the schema of the class, only the bytecode in method bodies. This can be quite a time saver in some situations, however it is certainly not a complete solution.
Fakereplace utilises a different approach, it works by transforming the bytecode of classes as they are loaded into the JVM in order to make them hot reloadable, and then it uses the java.lang.instrument api to hot swap the classes (this API allows you to redefine classes at runtime, with the same limitations at HotSwap). The modified classes are recompiled to that they appear to have been hot redeployed, even though the class schema has not changed.
Currently Fakereplace works with Jboss Seam 2.x, and is under heavy development. If you want to try it out it can be found here. If you would like to learn more about how it works, read on.
class Class1 { protected static int field; }
class Class1 { protected static int field; public static int getField() { return field; } public static void setField(int val) { field = val; } }
class Class1 { protected static int field; public static Object __REDEFINED_STATIC_METHOD_(int methodNo, Object[] parameters) { return null; } }
class Class1 { protected static int field; public static Object __REDEFINED_STATIC_METHOD_(int methodNo, Object[] parameters) { if(methodNo == 0) { return field; } if(methodNo == 1) { Integer p0 = (Integer)parameters[0]; int unboxedP0 = p0.intValue(); field = unboxedP0; return null; } return null; } }
public class FakeObject1 { public void setField(int param) { Object[] params = new Object[1]; params[0] = new Integer(param); Class1.__REDEFINED_STATIC_METHOD_(1,params); } }
Class.getMethods()
ReflectionDelegate.getMethods(Class clazz);
<t:MyClass> <t:myField>Hello World</t:myField> </t:MyClass>
<t:MyClass myField="Hello World" />