I'm experimenting with removing all @Components and moving beans into
an xml that could be read by spring to do DI.
This decreases the load time and

Errors:
- Abstract classes annotated as spring components
- Annotations for project which are not included in either build
profiles: usage, simulator, oss (default) and nonoss
- Some project don't even build or are not part of any build
artefacts, looks like the @Component annotation was done in a hurry :)
- Interfaces being annotated as spring components
- Prasanna, Abhi and I spoke with Spring gurus Vijay V and Vaibhav on
how to fix this bloat, so in applicationContext.xml we do some aop
stuff to have transaction stuff we get from @DB annotation and this
needs fixing as it's applying the following for all classes and
methods (dude bloat, run! :)

  <aop:config proxy-target-class="true">
    <aop:aspect id="dbContextBuilder" ref="transactionContextBuilder">
        <aop:pointcut id="captureAnyMethod"
            expression="execution(* *(..))"
        />

Methodology and results:
I wrote a python program that would go through the whole source code
and fix all java files (except test, awsapi) who have @Component and
create bean rules in an xml file. Next I had to manually fix few
things (see error above) and I got the mgmt server running, the load
time had improved a lot (little faster now) after disabling
autoscanning and just using the xml generated. I see the benefit of
just using the xml and not having spring as a build time dependency
(we're using @Component in our classes so :).

This was an experiment mostly because a lot of folks are having spring
memory issues, especially Prasanna's devcloud-ci cannot run and check
our commits as memory kills dom0. So, if no one objects may I go ahead
and commit it? For me the jvm took about 650MB real memory on osx.

Right now I made it for all build profiles, nonoss being the superset,
my experiment can be checked out from here:
https://github.com/bhaisaab/cloudstack/tree/spring-annotation-to-xml

Regards.

The python program, in case anyone wants to replicate or is curious:
(defaulter is just a file containing result of: file . | grep java$ >
defaulter)
f = open('defaulter', 'r')
files = f.read().split('\n')[:-1]
files = filter(lambda x: not x.startswith('./awsapi') and
x.find('/test/') == -1, files)
xmldata = ""
bean = """  <bean id="%s" class="%s"/>\n"""
xml = """<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements. See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership. The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License. You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied. See the License for the
  specific language governing permissions and limitations
  under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
  xmlns:context="http://www.springframework.org/schema/context";
  xmlns:tx="http://www.springframework.org/schema/tx";
  xmlns:aop="http://www.springframework.org/schema/aop";
  xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                      http://www.springframework.org/schema/tx
                      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                      http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                      http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd";>

%s
</beans>
"""
misses = []
for file in files:
    name = file.split('/')[-1].split('.')[0]
    name = name[0].lower() + name[1:]
    pkgname = ""
    idx = 0
    paths = file.split('/')[1:]
    paths[-1] = paths[-1].split('.')[0]
    for str in paths:
        if str == 'org' or str == 'com':
            pkgname = '.'.join(paths[idx:])
        idx += 1
    f = open(file, 'r')
    data = f.read()
    f.close()
    idx = data.find('@Component')
    if idx == -1:
        misses.append(file)
        continue
    string = '@Component'
    if data[len(string)+idx] == '(':
      endidx = data.find(')', len(string)+idx)
      name = data[len(string)+idx+1:endidx].split('=')[-1].replace('"', '')
      name = name.replace("'", '')
      data = data[:idx] + data[endidx+2:]
    else:
      data = data.replace(string, '')
    data = data.replace('import
org.springframework.stereotype.Component;\n', '')
    f = open(file, 'w')
    f.write(data)
    f.close()
    print name, pkgname
    xmldata += bean % (name, pkgname)
    xmldata += "\n"

xml = xml % xmldata
f = open('./client/tomcatconf/defaultComponentContext.xml.in', 'w')
f.write(xml)
f.close()

f = open('misses', 'w')
f.write('\n'.join(misses))
f.close()

Reply via email to