Blog

Implementing Review Board for Code Reviews

A few days ago I migrated our build server, aptly named Bob (the Builder), to Ubuntu 10.04 LTS and incorporated a new product to the existing suite. The new product is Review Board, which we’ll be using for regular code reviews within our development team. I’ve written previously on the various products we use as part of our continuous integration system, and Review Board has now joined their ranks as a much needed assistant helping us cast a human eye on code quality. We also use Sonar for code quality analysis, but that’s only one part of a very big picture. I’ve seen through experience how code reviews can significantly improve quality, and I know my own personal experience is very well supported by many books and blogs on the subject.

One challenge we have is fully integrating this into our development environment, as some developers work in ABAP and others in Java. The Java developerment environment neatly integrates with Review Board, but the ABAP has some interesting obstacles. What we’ve done to overcome this challenge is to write a proof of concept application in ABAP that allows a developer to export ABAP code (in a neat human-readable form) into a Subversion repository. From there, the developer can request a code review using the post-review command line tool. It all works as expected, but it’s still quite a manual, time-consuming process. We hope to develop this further, making it much easier to use, and roll it out to the other development teams.

The next decision we have to make is to choose whether to do pre-commit or post-commit reviews. Both have their strengths and weaknesses, so we’ve decided to try them both out before making a firm decision on how to take it forward.

Only a week or two in, and I’m already seeing the benefits of implementing Review Board! More updates to come as we iron out the creases in our review process…

Traversing the realms – Moving from .NET to Java

As some of you might notice, this is my first post here at G3, and after much deliberation about which topic I should address, I decided perhaps I should give my account of what I think moving from the world of .NET and C# to Java was like for me.

When I was initially considering taking up my current Java position, I knew then it was completely out of my comfort zone and that, by me taking this step would challenge me extensively for many months to follow. But before I’d just blindly take the leap, I began a bit of research. You know which research I’m talking about, the obligatory “.net to c#” and “is java better than .net” etc. Just to get a feel for the buzz out there. You can imagine that I was obviously inundated with more results than you could shake a stick at. And after many nights of reading “just one more article”, and ending up in bed at 2am, you realise that there is a lot of info out there. Along with all this info, I could help but feel a little sorry for Java because, whether rightfully substantiated or not, a lot of people seem to be giving the Java world a hard time. It wasn’t uncommon for me to read comments from others out there saying that it’s lagging behind, and that it’s going to become just another “Cobol”, and that .NET was the way forward, and it has so many more bells and whistles.

Of course, when you’re reading all of this negativity, it gives one some food for thought, that is of course until you find out the food for your thought wasn’t actually the sirloin beef with mushroom sauce you thought it was, but instead it’s really just a rice cracker with some marmite!

As I stubbornly ploughed through my research, what I found surprising, is the size of the Java community out there. We all (well me definitely) associate Java with its free and be free nature where typically contributions and or creations are free and should be shared, and it’s a concept which has definitely gained them a huge community. As a developer in the Java world, you are really spoilt for choice when it comes to free or cheap tools, from development environments, application frameworks, to build tools, just to name a few. Some may say that this is both a blessing and a curse, but right now, with me soaking up as much as I can – I’m considering it as a blessing.

I also noticed that the majority of Java driven initiatives, always try to follow a standard. Let’s take Apache Tomcat as a trivial example. Here is a lightweight web server container, which is packed with fantastic features, features you’d expect from a web server container, but where it’s really powerful is in its adherence to the JSP and the Java Servlet spec. Nothing more, and nothing less. It has provided the basis for many application servers out there, so you have the comfort of knowing, that if you develop your application to the standards laid out for you by the two above mentioned specs, then your application becomes very portable which is an attractive offering to have in this day and age, when your customers, needs are so different, from one to the next. I know this might sound naive, but I got excited by this fact, and for me the possibilities are endless, in terms of developing software that is capable of not only running on multiple platforms, but also under different application servers et al.

Now, getting back to me convincing myself that I was making the right move. I guess, after a lot of information overload, in the end, it was two realizations for me that helped me take the leap:

  1. When reading all the articles, blog entries and forum discussions, I personally seemed to notice that the individuals out there who gave the most objective and possibly more all-round answer or pro’s and con’s between the two platforms, whether it be discussing generics, or lambda expressions etc., they happened to be seasoned Java developers! What a coincidence? I’m not trying to insinuate that the .NET guys were rubbish, or incapable of offering all-round meaningful answers, but I guess I just noticed the Java guys defending with more tenacity, and this really stuck out for me.
  2. The more I read, the more I realised that it’s not the subtle syntax differences, or supposed “lacking” features from either platform which makes them good or bad, but rather one’s own application of experience and understanding of the base concepts in that particular platform. In other words, the differences shouldn’t matter if you’re a good enough developer!

I think you’ll agree that Java is by far a dying language, and it’s managed to come this far, despite the amount of abuse it may receive from others in the many different camps, not just .NET, yet it still has a massive community behind it all the way. Sure there might be some things which Java doesn’t have or can’t do, which .NET can and visa versa, but at the end of the day, both will fail miserably, if you have a poor design in place, or if you haven’t constructed your object hierarchy properly, or you’ve made inefficient use of memory. Basically poor understanding of base concepts equals a fail – no matter which platform you choose.

So with that said, I realised that taking on this new position shouldn’t pose a threat for my career, instead it will provide me the opportunity to actually gain an insight into the world of Java, and see how and what can be achieved on this platform. So far, I’m happy to report that I haven’t yet come across a scenario where I’ve said “oohhh I could really have done with that trusted .NET feature”, sure I might have instinctively started typing a declaration for a property, but then realised it should be a method instead. But it’s really just the same thing, done differently. And if I could say only one thing that you would take away from this article is this:

“Neither platform is particularly better or worse at providing application solutions; it’s just that you need to take a different approach to build them.”

Of course this is still early days, and I’ll be feeding back my experiences as I go, but hopefully this post will help any of you out there thinking of making the move.

G3 Global Reaping Rewards from Implementation of SAP Business All-in-One

G3 Global, SAP Value Added Reseller, implements SAP Business All-in-One at own company to manage business processes

SAP UKI today announced that G3 Global is now live with and already reaping the benefits of SAP Business All-in-One.  G3 Global, one of SAP UKI’s own leading channel partners selected SAP technology to help measure and achieve business objectives over the next five years.  As a Channel Partner, and now also a customer, G3 Global is now in a strong position when it comes to SAP.

G3 Global had outgrown its various disparate legacy systems and needed an integrated solution that would help it achieve its business strategy over the next five years.  G3 Global chose SAP Business All-in-One, which provides the full Enterprise Resource Planning (ERP) suite to the business, as it represented the most complete solution, and because of the strength of the SAP brand.  The implementation began on Christmas Eve 2009 and was completed in a rapid timescale of six weeks. 

Chris Gunter, G3 Global CEO, commented: “The implementation of SAP is vital for our strategic growth plans. We now have a real time integrated view across our entire business that has improved the reliability of our reporting, and increased the speed of decision making. Control has been placed in the hands of the right person within G3 Global leading to greater autonomy, significantly faster turnaround time and less burden on upper management. We are a now far more agile organization.”

Since going live G3 Global has realized a number of benefits including reducing month end close time from 14 days to just six hours, increased transparency and improved controls on and access to information.  G3 Global has now also been able to align its operations with industry best practice processes and set a solid foundation for cost effective future business performance by increasing visibility to real time information.  The company now plans to scale up and implement Business Intelligence and Customer Relationship Management (CRM) over the coming months. 

Stephen Read, Head of SME, SAP UKI said: “Our relationship with our customers and partners has always been a priority and now through G3 Global we are combining the two and I am delighted to see one of our partners using the SAP product they sell to make their own business run better.  G3 Global’s implementation has been nothing short of perfect, demonstrating that SAP technology can be implemented quickly and easily and that SAP offers quick time to value.”

G3 Global’s drive to constantly improve customer experience lead to the strap-line “drinking our own champagne”. This implementation has resulted in a very strong proposition and improved customer confidence knowing that G3 Global use the very solution they market and sell.

Gunter continued: “Being able to make informed decisions based on real time data has proved invaluable but the fact that we use what we sell is probably the biggest benefit we have seen so far. Knowing that G3 Global is committed to delivering a robust solution through our own experience has significantly improved customer confidence.”

On the 10 May, G3 Global was announced as a winner at the SAP UKI Quality Awards 2010, G3 Global was presented with the Gold award for best Small and Midsize Enterprise Implementation.

For more information (press only):

SAP UK Press Office at Burson Marsteller

Email: SAPUK@bm.com

Phone: +44 20 7300 6262

PDF Version – Media Release

Applying YSlow performance improvements within SAP NetWeaver

Having just finished reading Steve Souders’ High Performance Web Sites, I thought it would be helpful to point out how some of the server-side rules can be configured on SAP NetWeaver.

PS: Buy the book! It’s short and to the point, and very well written. I’ve already ordered his follow-up book Even Faster Web Sites to be delivered today!

The book covers 14 rules for improving performance on web sites, concentrating  mostly on front-end optimisations that can dramatically improve the responsiveness and user experience of your site. However, some of the rules involve changes on the server – for example, enabling gzip compression. The full listing of the Yahoo! Performance Rules can be found here.

Below is a brief summary of how to configure some of these rules in SAP NetWeaver. I’m using NetWeaver CE 7.1, so you may need to adjust these slightly if you’re running a different version. All configuration is done within NetWeaver Administrator > Configuration > Infrastructure > Java System Properties > Services, so I’m only going to mention that once to avoid repeating it many times over. I’ve also made an effort to reference the SAP Help docs that I’ve used to compile this summary, which you should find at the end of each section.

Rule: Add an Expires or a Cache-Control Header

The first thing to point out here is that NetWeaver has two cache control settings: one for the server and one for the client. Before understanding how to configure each of these, you need to know what it is that you’re configuring and the implications of the changes you’re about to make. I’ve included a diagram from the relevant SAP Help page (full reference below) to show the architecture of the ICM Server Cache.

The full explanation that accompanies this diagram can be found here: https://cw.sdn.sap.com/cw/docs/DOC-107069

Right… now that you have a better understanding of how caching works on the server, you’re ready to configure it. I assume you’re already familiar with the standard HTTP Cache-Control header, but refer you to the full explanation here if not: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9

In order to change the cache configuration, you need to find the HTTP Provider Service in NetWeaver Administrator and modify the following properties:

SapCacheControl – This should be set to the expiration period (in seconds) of the cached resource.
CacheControl – This can be set to any of the cache-response-directive values specified in the HTTP Specification (see link above for a reference to the section on Cache-Control).

You could argue that the server-side cache isn’t exactly what Steve Souders was talking about in his book – but when reading the documentation on the SAP Help site, you’ll see that the SapCacheControl value is also used as the Cache-Control max-age response directive… so it will have an impact on the cache status of web resources.

SAP Help Reference: https://cw.sdn.sap.com/cw/docs/DOC-100645

Rule: Gzip Components

Enabling gzip compression is fairly straight-forward. Just find the HTTP Provider Service in NetWeaver Administrator and modify the following properties:

AlwaysCompressed – This is a list of all the file extensions or MIME types that should always be compressed.
NeverCompressed – This is a list of all the file extensions or MIME types that should never be compressed.
CompressedOthers – Boolean value to indicate whether all other file extensions or MIME types (i.e. those not listed in either AlwaysCompressed or NeverCompressed) should be compressed.
MinimumGZipLength – Specifies the minimum size required for gzip compression to be applied. This property works in conjunction with AlwaysCompressed and CompressedOthers (i.e. the resource must be listed for compression AND larger than MinimumGZipLength in order to be compressed).

Note: File extensions must be in the format “*.ext”. Any entries without an asterisk will be treated as MIME types.

SAP Help Reference: https://cw.sdn.sap.com/cw/docs/DOC-111485

You can also dynamically enable compression for Servlet / JSP responses by passing special headers in the response. These headers are not sent to the client, but rather instruct the HTTP Provider Service to compress the response before sending it on to the client. These headers override the HTTP Provider Service configuration described above. If specified, the presence of these headers will force the HTTP Provider Service to either compress or not compress the response – regardless of what is configured elsewhere.

The header values themselves are configurable within the Web Container Service, and are described as follows:

HeaderForCompression – Specifies the header name that must force compression when present in the response
HeaderForNoCompression – Specifies the header name that must prevent compression when present in the response

To use this in your Servlet / JSP, simply set the relevant header to “true”.

SAP Help Reference: https://cw.sdn.sap.com/cw/docs/DOC-100076

Rule: Configure ETags

ETags are very elusive within the SAP Help docs. Despite much trawling, I could only come up with a few minor references to indicate that it exists – however no details could be found. I did find a SAP Note that mentioned a fix to ETag functionality in NW 7.0 – see Note 1020365.

If anyone manages to come across more information on this, please post a comment. I’d be interested in finding where it can be configured.

Criticism

While making all these configuration changes, it’s not hard to see that NetWeaver Administrator is lacking the user-friendliness that it should offer to administrators. It a fairly poor means of managing a system as it has been built to be as generic as possible. Unfortunately, in this case it means that there’s a lot it just doesn’t do very well because it’s trying to cater for everything in one go. To illustrate my point, simply try to modify the list of MIME types within the HTTP Service (see Mime property). This list is likely to be very long, regardless of how you configure it. What do you do if you want to add one extra MIME type? Well, in that case you need to copy the list already there and paste it into Notepad, add the item you want, then re-insert the entire list into an input field only wide enough for about 20 characters. To put that into perspective, the default list of MIME types is just under 4000 characters long. Not only is the input field far too small, but surely an administrator should be able to modify the existing list rather than recreating it to make a small change? Even worse than this is the fact the modified property text is not wrapped in the table cell. So if you do decided to add a MIME type, you lose all visibility of what has been configured as you can only see the first few characters before they disappear. I can’t say I’m surprised though. Usability has never been something that SAP do well… or at all, for that matter. However, taking visibility of the configuration of a system away from the administrator is a very dangerous thing to do. This issue very clearly illustrates how poor usability can have very far reaching consequences, and why it is so important to get it right!

This is by no means a comprehensive review of the how’s and why’s of each of these rules, nor does it go into much detail about each system property described. I intentionally kept this fairly straight forward so it can serve as a reference guide, and have instead provided links to more detailed documentation wherever I can. After all, the links are where I got the information in the first place – so it’s only right to give the original author full credit for it. I’m just hoping to save some of you time in finding the right resources.

I hope this has been helpful, even if it was nothing more than a prompt to look into other areas where NetWeaver can be configured to operate according to what you need.

G3 Global Graduate Program: Applications Closed

G3 Global received hundreds of applications for its Graduate Program at the Earl’s Court Summer Graduate Fair held on 9th and 10th of June.

The opportunity to submit an application for the Graduate Program has closed and all applicants have been advised of their success.

G3 Global would like to thank the new graduates who expressed an interest in the company by submitting an application.

For more information regarding career opportunities at G3 Global, please visit the Careers page.

Thoughts on Joining an Open Source Project

Since starting my career as a software developer back in 2002, I’ve wanted to join an open source project. A few things have held me back from doing this… including inexperience in my early career, lack of available time to commit properly to a project, and the inherent difficulty in finding that one project amongst the thousands out there that I feel strongly about. Over the last few weeks I’ve been looking into this again and have now decided to join OpenMRS. The experience of choosing a project and getting stuck in has prompted me to write about why I did it and hopefully spark some new ideas for other developers wanting to get involved in open source projects.

Why join an open source project?
Everyone has the capacity to get involved in something and help out, and software developers are no exception. I’ve always been involved in building software for business use, which has a lot of challenges and rewards – but it doesn’t really improve anyone’s life in any significant way. My reason for joining an open source project is to contribute to something that really matters… something that might genuinely improve the lives of other people. For this reason, I’ve focused on finding a project that has this as one of its core objectives.

Why OpenMRS?
The answer to this question is pretty simple… I have fairly limited “free” time as it is, so I wanted to make sure I join a project that I believe in. OpenMRS is clearly focused on providing software that can improve the lives of millions of people – particularly in the developing world – so this immediately caught my attention. My original career plan was to study medicine and become a surgeon, but after finishing school I made the decision to study software engineering instead. I don’t regret that decision, but I’ve never lost my interest in medicine, and joining the OpenMRS project gives me the opportunity to work in both.

What’s next?
When joining any new project there is always a lot to learn. Others may have been involved for years, but you have to learn the ropes before you can be of any use to the existing team. So my focus for the next few weeks will be to learn about OpenMRS from every conceivable perspective. What problem is the system trying to solve? How does it work for the user? How has it been designed? How is the data model structured? However, the biggest challenge will be gaining enough understanding of the medical domain for the system to make sense. Very fortunately, the technical foundation is quite familiar territory – so the biggest obstacle is domain knowledge.

I’ll follow up in the coming weeks with some details on how to contribute to an open source project – entirely based on my experience, rather than a definitive list of “do’s and don’ts”. Until then, I’ll be buried in documentation!

Adopting the Agile methodology, a personal retrospective

Having spent more years than I’m prepared to admit working on IT projects, facing up to a challenge of adopting the Agile Scrum methodology filled me with a mixture of excitement and dread!

My whole working life has been spent on software development and support projects. Along the way I’ve worn many hats; developer, business analyst, team lead, project manager and department manager. The projects have ranged from multi-million Pound/Dollar projects spanning many years, adopting various incarnations of waterfall methodologies, through to smaller projects run using the JFDI approach (Just Focus and Do It, is one of many definitions of JFDI, although some of my managers have found blunter substitutes for “Focus”)

18 months ago, I was wearing a couple of hats on a web development project for a client based in the USA. The project was being run using a tried and tested variation of the waterfall methodology. My role encompassed Analysis and Design as well as Development and testing. I’d been out of coding for a few years, and this was my first real web development project of note. Not only was I developing in a new language, I was also doing my best to manage the paradigm shift from procedural programming to true Object Oriented design and development. Thankfully I was working with a seasoned OO professional, who took time to explain concepts, but also gave me enough rope to tie myself in knots and work my way out again. In summary, I was enjoying the challenge, but feeling somewhat vulnerable as I was out of my comfort zone.

In truth, the project was lacking momentum and needed a different approach. Enter, Agile and Scrum. The idea was presented by Stuart, who’d experienced the benefits of Agile development in the past. We discussed what it would mean for us as a team, and us as individuals; daily stand-up meetings, smaller development iterations, commitment to each other about what we would deliver and when.

Outwardly, I embraced the idea and concept, and even muttered that I was excited by it. Internally, the voice of paranoia was telling me that it would expose my coding weaknesses and highlight my unrealistic estimates. In truth, I was curious and keen to try it, “nothing ventured, nothing gained” was how I saw it, and I had to trust that this was being tried for the right reasons.

Before I reflect on how it impacted me and the project delivery, it’s probably worth explaining what we did as well as a simplified overview of the processes adopted.

Agile-Scrum-Sprint-Process

Agile Scrum Sprint Process Flow

The backlog

To start with, we worked through all outstanding development tasks and estimated the effort required to complete each feature. We broke features down into user stories, to allow us to isolate discrete “potentially shippable” pieces of development. These user stories formed the backlog, the list of deliverables that were outstanding. We then prioritised the backlog based on what we knew to be the client’s priorities and also what made technical sense due to dependencies.

Planning sessions

One of the core elements of the Agile approach is the concept of iterations. We adopted the Scrum Methodology, so our iterations became Sprints. Our early Sprints were based on 20 working days. Before we started the Sprint, we had to agree and commit to what we would deliver at the end of the Sprint. The key difference now being that the developments would have to be potentially shippable, not just unit tested. In the planning session we established our velocity. The velocity was calculated establishing the realistic number of productive hours a day for each person, then multiplying it by the 20 days. We were then able to say than in 20 days, we had the capacity to deliver x hours of development.

Having established our velocity for each Sprint, each one would be different depending on resource, holidays etc., we were then able to select user stories from the backlog that we could commit to during the Sprint. At this stage we expanded the user stories down to task level, and put estimates against each task. This was the first chance we had to measure our story estimates against the sum of the tasks. In effect, we’d planned a 20 day mini project although I’m sure purist Agile practitioners would frown at that description.

Daily Stand-up meetings – the Scrum!

Each morning we would meet at the same time and answer 3 questions each, nothing more, nothing less.

  1. What did you do yesterday?
  2. What are you going to do today?
  3. Are there any obstacles (blockers) that are preventing you from being able to deliver?

In effect, we were making commitments to each other, I will do this today, and tomorrow I will either confirm that I’ve completed what I said I do, or explain why I haven’t been able to. One of the interesting elements of this session was that we were free to choose what we wanted to work on, as long as nobody else had already claimed it. This did lead to some interesting issues which I’ll follow up on in a future blog.

Sprint Burn-down Chart

Burn-down Chart from 1st Sprint

The burn-down chart measured where we were against our projected estimates. Key to making the burn-down work, was recording how much time we had spent, and importantly how much time was left. This required both honesty and discipline to make it of any use. If a particular task was estimated at 10 hours, and in a given day I’d spent 6 hours on it, I would have to record the fact that I’d spent 6, and how many hours were outstanding. The temptation of course was to say 4, as that’s what we estimated (10-6), but sometimes it was more, it could actually be another 6 or 8 hours. This was an important lesson learnt. It highlighted where we’d under or overestimated, and it also gave us a better gut feel as to what our true capacity to deliver was.

So how did it impact me?

My fears were unfounded! The process allowed me to feed into the estimating process, with how long I thought it would take me. This meant that the sprint was weighted at an appropriate level. There was no benefit in estimating based on the quickest developer, when there would be more junior people working on the tasks. It’s preferable for a senior to come in under at say 70% of estimated time rather than a less experienced developer constantly coming in over at 130%. Some tasks were by their nature going to fall to certain people, so in those cases, we could be more accurate with our estimating.

My personal productivity and that of the team increased. The use of the Sprint burn-down chart, helped identify early on if we were off target.

When we set out to try the Agile approach, we set ourselves a target of 2 or 3 Sprints to give it a chance to work. After each Sprint, we had a retrospective to reflect and what had worked, what hadn’t and what improvements we could take into the next Sprint. We didn’t need 2 or 3 Sprints to realise that this was the way forward.

We started to deliver output, productivity increased, team communication improved, and we all worked towards the same goal. Agile is definitely here to stay for our team. Over the 18 months, the project has moved through different phases, pre and post go-live. The team has flexed and changed and we have tried refining the process to adjust to those different phases. I will explore these issues in another retrospective blog about our experiences of adopting Spints and Kanban.

Would I go back to waterfall based project methodologies? No!

What’s the longest class name you’ve ever seen?

When trying to do code completion for “Hashtable”, I was instead presented with this incredibly long class name! Priceless!

HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor

Believe it or not, it really does exist. It’s contained within package “org.aspectj.weaver.patterns”, and can be verified here: http://www.springsource.com/repository/app/bundle/version/export?name=com.springsource.org.aspectj.matcher&version=1.6.8.RELEASE&package=org.aspectj.weaver.patterns

Has anyone else found anything longer than that? Now I’m curious to know what else is out there!

I’m also beginning to wonder whether a new site needs to be created called www.codecompleteme.com in the same spirit as www.autocompleteme.com :-)

Graduate Applications to be Assessed

G3 Global has received a huge response to its Graduate Program following the Summer Grad Fair held at Earl’s Court on Wednesday 9 and Thursday 10 June.

Over two days, the G3 Global team received hundreds of applications which will now be assessed and culled down to find the best applicants.

The selection process will continue over the next two weeks and all graduate applicants will be advised of their success in gaining a position by the end of the month.

There is no set number of positions on offer and no set position types. G3 Global is recruiting across a wide range of specialities including marketing and sales, information technology and project management. The number of positions will be reliant on how many suitable applicants are identified.

Graduates who are interested in applying are still invited to submit an application, which can be downloaded from the link below.  Once the application is complete, it should be emailed to careers@g3it.com.

For the G3 Global Graduate Program Application Form click here.

G3 Global Calling for Graduate Applicants at Summer Grad Fair

G3 Global appeared at the Summer Graduate Fair held at Earl’s Court Exhibition Centre today where consultants spoke to hundreds of students about graduate opportunities currently available.

The organisation believes that the fastest way to learn is on the job, by performing real tasks internally and for clients.  Positions are available through G3 Global’s Graduate Program which offers opportunities for a wide range of specialties such as business management, information technology and marketing and sales.  

Successful Graduate Program applicants will work under the close supervision of department managers to help them learn the G3 Global business and maximise their potential through engaging with real clients and requirements.

Applicants can look forward to being part of an exciting and challenging environment where they can apply and expand their existing skills and knowledge.

The graduate will become part of the small, high-performing consultancy that is committed to developing its people through gaining access to the latest SAP products and technologies.

Graduates who are interested in applying are invited to submit an application, which can be downloaded from the link below.  Once the application is complete, it should be emailed to careers@g3it.com.

For the G3 Global Graduate Program Application Form click here.