Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Tuesday, 17 September 2013

eclipse extension bundle timeout errors

If you find that eclipse is failing to install bundles or extensions with timeout errors then try adding this line to your INI file.

    -Dsun.net.client.defaultReadTimeout=30000

I use the spring sourse STS variant of eclipse so my file is called STS.ini but yours might be ECLIPSE.ini


Friday, 23 September 2011

finding the correct spring jar for a known class

With Spring 3 you now have to get all the individual jars that you need for an application.

One solution is obviously to download the lot.

But what if you just want to install what is needed.
How do you easily find which jar a class is in ?

Well I have just found this Spring Bundle Search tool.

You can enter just the class name or the class with its full package name.

Monday, 4 July 2011

Auditing using AOP and annotations in Spring

Lord, how I dislike the old XML configuration for AOP (among other things).

I have not given myself the opportunity to try out Spring's annotation based AOP in spring, until now and boy is it easy (with one minor gotcha).

Here are the building blocks:

1) Make your own Annotation. This is a simple way to mark all methods you want to audit.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ParmsAudit
{
  ActionAuditType  auditType();
}


2) ActionAuditType is an enum that will be used to identify the thing being audited.

public enum ActionAuditType {
USER_LOGGED_IN("User Logged In"),
USER_LOGGED_OUT("User Logged Out");

private String mDescription;
  private ActionAuditType(String aDescription) {
 mDescription = aDescription;
}


public String getDescription() {
 return mDescription;
}
public void setDescription(String aDescription) {
 mDescription = aDescription;
}
}

3) Create an Aspect. This is the code that is run when the method marked by the annotation is called.

Here is the minor gotcha - well for me atleast.
I had to list the full package path to the Annotation in the @Before statement.


@Aspect
public class AuditAspect {

@Before(value="execution(@uk.co.billcomer.audit.ParmsAudit * *(..)) &&   @annotation(parmsAudit)", argNames="parmsAudit")
public void logTheAuditActivity(JoinPoint aPoint, ParmsAudit parmsAudit) {
 String userName = getUserName();
 mlogger.info("Parms Auditing User Name: " + userName);
 mlogger.info("auditType:" + parmsAudit.auditType().getDescription());

 String arguments = getArgs(aPoint.getArgs());

 if (arguments.length() > 0) {
 mlogger.info("args-" + arguments);
 }
}

private String getArgs(Object[] args) {
 String arguments = "";
 int argCount = 0;

 for (Object object : args) {
   if (argCount > 0) {
     arguments += ", ";
   }
   arguments += "arg[" + ++argCount + "]=" + "[" + object + "]";
 }
 return arguments;
}

private String getUserName() {
 try {
   return SecurityContextHolder.getContext().getAuthentication().getName();
 } catch (NullPointerException npe) {
   return "Unknown User";
 }
}
}

4) Mark the method to be audited.


@Service("parms.DummyAuditThing")
public class DummyAuditThing implements DummyAudit {

@Override
@ParmsAudit(auditType = ActionAuditType.USER_LOGGED_IN)
public void aspectAuditMethodTwoParams(String param1, Long param2) {
 mlogger.info("In method to be audited param1[" + param1 + "], p2[" + param2 + "]");
}
}


5) Context configuration
This is needed to speed up the compilation process. Essentially it tells the compiler what classes will have Aspects
   
   <aop:aspectj-autoproxy proxy-target-class="true"/>   
   
   <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
   <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
   
   <bean id="bill.auditAspect" class="uk.co.billcomer.audit.AuditAspect" />

Thursday, 24 February 2011

FileUpload with multipart/form-data in Spring 2.5.x and Annotations

Firstly a qualifier, This is for Spring 2.5.x with annotations.
I have not had the pleasure of upgrading to Spring 3.X yet.

There is some excellent documentation on File Upload with Spring.

However for an annotation driven Controller it misses out one important step, namely the @InitBinder annotation.

@InitBinder
public void initBinder(ServletRequestDataBinder aBinder) throws ServletException {
// to actually be able to convert Multipart instance to a String
// we have to register a custom editor
aBinder.registerCustomEditor(String.class, new StringMultipartFileEditor());
// now Spring knows how to handle multipart object and convert them
}


Wednesday, 24 November 2010

eclipse, junit & static imports

It was annoying me that eclipse was not finding the static imports needed by junit 4 unit tests.

A quick google tuned up this gem, which I have grabbed below:

Open the Preferences via Window -> Preferences and select Java > Editor > Content Assist > Favorites. Add then via "New Member" the methods you need. For example this makes the assertTrue, assertFalse and assertEquals method available.

You can now use Content Assist (Ctrl+Space) to add the method and the import.

He suggests to add at least the following new members.

  • org.junit.Assert.assertTrue

  • org.junit.Assert.assertFalse

  • org.junit.Assert.assertEquals

  • org.junit.Assert.fail

I suggest also adding

  • org.junit.Assert.assertNotNull

Friday, 15 May 2009

TDD Testing of Dependancy Injection in Spring

Spring relies very heavily on dependancy injection and when writing integration tests the first thing that must work before you even try to connect to things like your database is that all your beans must be correctly injected.

So before I get all excited and start writing tests that read or write to the database I write a very simple test to check that everything has been injected correctly.

public class FooServiceIntegrationTest extends BaseIntegrationTester{
private FooService fooService;

public void setFooService(BulkUploadService aFooService){
fooService = aFooService;
}

public void testInjection() throws Exception{
assertNotNull("FooService not injected", fooService);
}
}

Strictly speaking this test testInjection is not needed at this stage because the test will fail if the injection of this primary bean fails.

Ok so I need to create the bean.

<bean id="fooService" name="fooService" class="uk.co.foo.FooServiceImpl">
</bean>

The test will now pass.

The test now gets more useful as I now extend the test to see if FooService has its beans injected successfully.

public class FooServiceIntegrationTest extends BaseIntegrationTester{
private FooService fooService;

public void setFooService(BulkUploadService aFooService){
fooService = aFooService;
}

public void testInjection() throws Exception{
assertNotNull("FooService not injected", fooService);
assertNotNull("FooService not injected", fooService.getBarDao());
}
}

Now this will not compile at first as fooService.getBarDao() does not exist.
I add this to the interface and implement the method and re-run the test,

The test fails as we have not set the property on the bean so lets do that.

<bean id="fooService" name="fooService" class="uk.co.foo.FooServiceImpl">
<property name="barDao" ref="barDao" />
</bean>

Assuming barDao has also been configured then the test will now pass.

Possibly others do this, I do not know but I have found this little test invaluable as a precursor to grander integration tests later on.

BTW BaseIntegration tester does little more than extend AbstractTransactionalDataSourceSpringContextTests and implement the method getConfigLocations()

Thursday, 9 April 2009

Spring User Group in the North West

Last night was the inaugrial North West Spring User Group.

There were two speakers, Jan Machacek of Cake Solutions and a joint author of Pro Spring 2.5 and Rob Harrop from SpringSource and also joint author with Jan on the original 'Pro Spring' book

Jan gave an excellent worked example of a small web application using Spring 3.0 and Rob also ran a worked example on REST development in Spring. Rob's talk was particularly interesting and brave in that he was willing to show the REST development at the cutting edge and show and admit to its weaknesses with it being only at milestone release.

There will be future meetings and you can follow them at the Linkedin User group

Thursday, 29 January 2009

NTLM Authentication and the IE Post Problem

We are using NTLM Windows Authentication for a Single Sign On (SSO) project.

We are using the Spring security Filter NtlmProcessingFilter which for most of the time is absolutely fine.

However the are atleast two scenarios where this fails.

1) When the session is timed out and a form.submit() request is made.
Under this situation a windows logon box is presented. This is obviously not desirable in a SSO project.

2) If the page makes heavy use of dwr/javascript.
In this case the page makes repeated NTLM authentication requests and stack traces are observed with the message 'This is not a Type 3 Message'.

There is a solution described in the jcifs documentation. Search for registry key. This solution works but is not suitable for us as our client would not let us change the registry on all the client PCs. Quite understandably I think.

The fix described here applies to Spring-Security 2.0.4 and jcifs 1.2.25 but is also required for jcifs to atleast 1.3.3

Both Spring-Security and jcifs have an NTLMFilter and it is to this that the fix is required.

Here is the Spring solution to org.springframework.security.ui.ntlm.NtlmProcessingFilter:


protected void doFilterHttp(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final HttpSession session = request.getSession();
Integer ntlmState = (Integer) session.getAttribute(STATE_ATTR);

final String authMessage = request.getHeader("Authorization");

// Check the special IE POST request with Authorization header containing
// type-1 message (see method javadoc)
if (this.reAuthOnIEPost(request)) {
if ((authMessage != null) && (authMessage.startsWith("NTLM "))) {
logger.debug("POST Request with NTLM Authorization detected.");
// decode the NTLM response from the client
byte[] src = Base64.decode(authMessage.substring(5));
// see if a type 1 message was sent by the client
if (src[8] == 1) {
logger
.debug("NTLM Authorization header contains type-1 message. Sending fake response just to pass this stage...");
Type1Message type1 = new Type1Message(src);
// respond with a type 2 message, where the challenge is null since we
// don't
// care about the server response (type-3 message) since we're already
// authenticated
// (This is just a by-pass - see method javadoc)
Type2Message type2 = new Type2Message(type1, new byte[8], null);
String msg = Base64.encode(type2.toByteArray());
response.setHeader("WWW-Authenticate", "NTLM " + msg);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.flushBuffer();
}
}
} else {
..... existing filter code
}
chain.doFilter(request, response);
}

The fix for jcifs appears to be very similar and thanks to Asaf Mesika off the jcifs forum for his help. NB: I have not tried this jcifs solution. For jcifs the fix is to jcifs.http.NtlmHttpFilter:


protected NtlmPasswordAuthentication negotiate( HttpServletRequest req,
HttpServletResponse resp,
boolean skipAuthentication ) throws IOException, ServletException {
UniAddress dc;
String msg;
NtlmPasswordAuthentication ntlm = null;
msg = req.getHeader( "Authorization" );
boolean offerBasic = enableBasic && (insecureBasic || req.isSecure());

// Check the special POST request with Authorization header containing type-1 message (see method javadoc)
if (request.getMethod().equalsIgnoreCase("POST")) {
String authorization = request.getHeader( "Authorization" );
if ( (authorization != null) && (authorization.startsWith("NTLM ")) ) {
logger.debug("POST Request with NTLM Authorization detected.");
// decode the NTLM response from the client
byte[] src = Base64.decode(authorization.substring(5));
// see if a type 1 message was sent by the client
if (src[8] == 1) {
logger.debug("NTLM Authorization header contains type-1 message. Sending fake response just to pass this stage...");
Type1Message type1 = new Type1Message(src);
// respond with a type 2 message, where the challenge is null since we don't
// care about the server response (type-3 message) since we're already authenticated
// (This is just a by-pass - see method javadoc)
Type2Message type2 = new Type2Message(type1, new byte[8], null);
String msg = Base64.encode(type2.toByteArray());
response.setHeader("WWW-Authenticate", "NTLM " + msg);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.flushBuffer();
return false;
}
}
}

... existing filter code ....
}

I have raised a spring-security bug if you want to see if it is fixed in the version you have.

Monday, 17 November 2008

Spring source for minor spring projects and many others !

A while ago I struggled to find a Spring security test class TestingAuthenticationToken following an upgrade to spring-security from acegi.

Turned out it had been moved out of the standard release causing my tests to fail with a ClassNotFoundException. You will find it in spring-security-core-x.y.z-tests.jar for the relevant version.

Similarly, I wanted to see the source for a test class
org.springframework.test.AbstractTransactionalDataSourceSpringContextTests. This again can found on the same site as can the source for all spring modules. The root for spring modules is here.

Being more nosey you will find the source for may other projects (such as apache, eclipse, dbunit) by navigating further up the tree. Happy hunting.

Tuesday, 4 November 2008

DWR, Spring and namespace configuration

I am in the process of upgrading an existing Spring based web application that also uses DWR for alot of its dynamic pages.

The current version of Spring is 1.2.7 and part of the upgrade is to move to Spring 2.5.5

Spring 2.x now supports the namespace style of XML config files which produces a dramatically smaller & easier to read configuration. I produced a working version of configuration in both the old style and the namespace style but stuck with the latter as this is the future.

The version of DWR is 1.1.3 and its configuration requires a config file dwr.xml in the old style.

All was going well until I started spotting Exceptions being thrown by DWR.
java.io.IOException: The specified call count is not a number: null
at uk.ltd.getahead.dwr.impl.ExecuteQuery.parseParameters(ExecuteQuery.java:427)
at uk.ltd.getahead.dwr.impl.ExecuteQuery.execute(ExecuteQuery.java:89)
at uk.ltd.getahead.dwr.impl.DefaultExecProcessor.handle(DefaultExecProcessor.java:48)
at uk.ltd.getahead.dwr.impl.DefaultProcessor.handle(DefaultProcessor.java:81)
at uk.ltd.getahead.dwr.AbstractDWRServlet.doPost(AbstractDWRServlet.java:162)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
......

Upgrading to DWR 2.0.5 simply caused the Exception to disappear, but instead I got a popup stating much the same.

The problem is because I chose to use the namespace syntax for my configuration. One solution was to revert to the old style. Due to the size of the app and timescales I chose this option.

The other option is far nicer but a lot more work and that is to upgrade my DWR to 2.0.5 and change the configuration to also use the namespace syntax. This would create a solution with much better integration between DWR and Spring. I will try that out on my next application.

See DWRs documentation and Bram Smeet's blog on this topic for an excellent how-to.

Saturday, 5 April 2008

hibernate3 - hibernateQueryException - Class is not mapped

I have been having a problem for a while trying to get a basic hibernate3 and Spring 2.5 example working. Using old style hibernate CLASS_NAME.hbm.xml files worked fine. When I changed the context.xml file to try & use annotations instead I got the following error:

Exception in thread "main" org.springframework.orm.hibernate3.HibernateQueryException:
Test is not mapped [from Test t where t.name = ?];
nested exception is org.hibernate.hql.ast.QuerySyntaxException:
Test is not mapped [from Test t where t.name = ?] at
org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:640)


Check the imports of your '@Entity' annotations in your beans

If it is:
    org.hibernate.annotations.Entity;
Then change it to:
    import javax.persistence.Entity;
and life will be sweet.

Wednesday, 5 March 2008

UnitTest and spring-mock or spring-test

I have just installed spring 2.5.1

I wanted to create some unit tests and all the sites I found referred to spring-mock.jar.

It is now spring-test.jar.

You will find it in the directory spring-framework-2.5.1/dist/modules after you have extracted the zip. I downloaded spring-framework-2.5.1-with-dependencies.zip although I see they have gone to 2.5.2 already.