Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
use separate asynchronous factory bean to create the MavenIndexerFaca…
…de - and use a Timer to avoid the WAR blocking on startup of the indexer as the indexer can take a while to start
  • Loading branch information
jstrachan committed Mar 26, 2013
1 parent e564aa0 commit 3ebf595
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 68 deletions.
@@ -0,0 +1,125 @@
/**
*
* 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.
*/
package io.hawt.maven.indexer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

/**
* A factory bean of an {@link MavenIndexerFacade} which starts itself completely
* asynchronously; since the indexer typically takes quite a while to startup.
*/
public class AsyncMavenIndexerFacadeFactory {
private static final transient Logger LOG = LoggerFactory.getLogger(AsyncMavenIndexerFacadeFactory.class);

private MavenIndexerFacade mavenIndexer;
private boolean updateIndexOnStartup = true;
private ObjectName objectName;
private MBeanServer mBeanServer;
private String[] repositories;

private File cacheDirectory = new File("mavenIndexer");

public void init() {
Timer timer = new Timer("MavenIndexerFacade startup timer");
TimerTask task = new TimerTask() {
@Override
public void run() {
try {
LOG.info("Starting to create the MavenIndexerFacade");
createMavenIndexer();
LOG.info("Completed creating the MavenIndexerFacade");
} catch (Exception e) {
LOG.error("Failed to create the MavenIndexerFacade: " + e, e);
}
}
};
timer.schedule(task, 3000);
LOG.info("Started the async timer to create the MavenIndexerFacade after the application starts up");
}

public void destroy() throws InstanceNotFoundException, IOException, MBeanRegistrationException {
if (mavenIndexer != null) {
mavenIndexer.destroy();
}
}

public File getCacheDirectory() {
return cacheDirectory;
}

public void setCacheDirectory(File cacheDirectory) {
this.cacheDirectory = cacheDirectory;
}

public MBeanServer getMBeanServer() {
return mBeanServer;
}

public void setMBeanServer(MBeanServer mBeanServer) {
this.mBeanServer = mBeanServer;
}

public ObjectName getObjectName() {
return objectName;
}

public void setObjectName(ObjectName objectName) {
this.objectName = objectName;
}

public String[] getRepositories() {
return repositories;
}

public void setRepositories(String[] repositories) {
this.repositories = repositories;
}

public boolean isUpdateIndexOnStartup() {
return updateIndexOnStartup;
}

public void setUpdateIndexOnStartup(boolean updateIndexOnStartup) {
this.updateIndexOnStartup = updateIndexOnStartup;
}

protected void createMavenIndexer() throws Exception {
mavenIndexer = new MavenIndexerFacade();
mavenIndexer.setUpdateIndexOnStartup(updateIndexOnStartup);
if (objectName != null) {
mavenIndexer.setObjectName(objectName);
}
if (mBeanServer != null) {
mavenIndexer.setMBeanServer(mBeanServer);
}
if (repositories != null) {
mavenIndexer.setRepositories(repositories);
}
mavenIndexer.start();
}
}
Expand Up @@ -53,7 +53,6 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;

/**
* A facade over the Maven indexer code so its easy to query repositories
Expand All @@ -76,7 +75,6 @@ public class MavenIndexerFacade implements MavenIndexerFacadeMXBean {
};
private File cacheDirectory = new File("mavenIndexer");
private Map<String, IndexingContext> indexContexts = new HashMap<String, IndexingContext>();
private CountDownLatch startedSignal = new CountDownLatch(1);

public MavenIndexerFacade() throws PlexusContainerException, ComponentLookupException {
this.plexusContainer = new DefaultPlexusContainer();
Expand All @@ -96,73 +94,44 @@ public void start() throws ComponentLookupException, IOException, MalformedObjec
}

// now lets create all the indexers
Thread thread = new Thread("MavenIndexer index thread") {
@Override
public void run() {
try {
for (String repository : repositories) {
if (StringUtils.isNotBlank(repository)) {
String url = repository;
String id = repository;
int idx = repository.indexOf('@');
if (idx > 0) {
url = repository.substring(0, idx);
id = repository.substring(idx + 1);
}
File repoDir = new File(cacheDirectory, id);
File cacheDir = new File(repoDir, "cache");
File indexDir = new File(repoDir, "index");
cacheDir.mkdirs();
indexDir.mkdirs();
String contextId = id + "-context";

IndexingContext repoContext = indexer.createIndexingContext(contextId, id, cacheDir, indexDir,
url, null, true, true, indexers);
indexContexts.put(id, repoContext);
}
File mergedDir = new File(cacheDirectory, "all");
File cacheDir = new File(mergedDir, "cache");
File indexDir = new File(mergedDir, "index");
ContextMemberProvider members = new StaticContextMemberProvider(indexContexts.values());
mergedContext = indexer.createMergedIndexingContext("all-context", "all", cacheDir, indexDir, true, members);
try {
for (String repository : repositories) {
if (StringUtils.isNotBlank(repository)) {
String url = repository;
String id = repository;
int idx = repository.indexOf('@');
if (idx > 0) {
url = repository.substring(0, idx);
id = repository.substring(idx + 1);
}
if (updateIndexOnStartup) {
downloadOrUpdateIndices();
}
} catch (IOException e) {
LOG.error("Failed to update the maven repository indices: " + e, e);
}
try {
registerMBean();
} catch (Exception e) {
LOG.error("Failed to register MBean: " + e, e);
File repoDir = new File(cacheDirectory, id);
File cacheDir = new File(repoDir, "cache");
File indexDir = new File(repoDir, "index");
cacheDir.mkdirs();
indexDir.mkdirs();
String contextId = id + "-context";

IndexingContext repoContext = indexer.createIndexingContext(contextId, id, cacheDir, indexDir,
url, null, true, true, indexers);
indexContexts.put(id, repoContext);
}
startedSignal.countDown();
File mergedDir = new File(cacheDirectory, "all");
File cacheDir = new File(mergedDir, "cache");
File indexDir = new File(mergedDir, "index");
ContextMemberProvider members = new StaticContextMemberProvider(indexContexts.values());
mergedContext = indexer.createMergedIndexingContext("all-context", "all", cacheDir, indexDir, true, members);
}
};
thread.run();
}

protected void registerMBean() throws MalformedObjectNameException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
if (objectName == null) {
objectName = new ObjectName("io.hawt.maven:type=Indexer");
}
if (mBeanServer == null) {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
mBeanServer.registerMBean(this, objectName);
}

public void startAndWait() throws MalformedObjectNameException, ComponentLookupException, IOException, MBeanRegistrationException, InstanceAlreadyExistsException, NotCompliantMBeanException {
start();
while (startedSignal.getCount() > 0) {
try {
startedSignal.await();
} catch (InterruptedException e) {
LOG.warn(e.getMessage(), e);
if (updateIndexOnStartup) {
downloadOrUpdateIndices();
}
} catch (IOException e) {
LOG.error("Failed to update the maven repository indices: " + e, e);
}
try {
registerMBean();
} catch (Exception e) {
LOG.error("Failed to register MBean: " + e, e);
}
LOG.info("MavenIndexer has finished updating its indices, its started");
}

public void downloadOrUpdateIndices() throws IOException {
Expand Down Expand Up @@ -215,11 +184,11 @@ public void destroy() throws IOException, MBeanRegistrationException, InstanceNo
}
}

public MBeanServer getmBeanServer() {
public MBeanServer getMBeanServer() {
return mBeanServer;
}

public void setmBeanServer(MBeanServer mBeanServer) {
public void setMBeanServer(MBeanServer mBeanServer) {
this.mBeanServer = mBeanServer;
}

Expand Down Expand Up @@ -393,6 +362,19 @@ protected BooleanQuery createQuery(String groupId, String artifactId, String ver
return bq;
}

// Implementation methods
//-------------------------------------------------------------------------

protected void registerMBean() throws MalformedObjectNameException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
if (objectName == null) {
objectName = new ObjectName("io.hawt.maven:type=Indexer");
}
if (mBeanServer == null) {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
mBeanServer.registerMBean(this, objectName);
}

protected BooleanQuery createTextSearchQuery(String searchText) {
BooleanQuery bq = new BooleanQuery();
if (StringUtils.isNotBlank(searchText)) {
Expand Down
Expand Up @@ -15,7 +15,7 @@
</ext:property-placeholder>
-->

<bean id="mavenIndexer" class="io.hawt.maven.indexer.MavenIndexerFacade" init-method="start" destroy-method="destroy">
<bean id="mavenIndexer" class="io.hawt.maven.indexer.AsyncMavenIndexerFacadeFactory" init-method="init" destroy-method="destroy">
</bean>
</blueprint>

Expand Up @@ -38,7 +38,7 @@ public static void init() throws Exception {
String[] repositories = {"http://repo.fusesource.com/nexus/content/groups/ea@fusesource-ea-repo"};
facade.setRepositories(repositories);
facade.setCacheDirectory(new File(targetDir(), "fuse-ea-mavenIndexer"));
facade.startAndWait();
facade.start();
indexer = facade;
}

Expand Down

0 comments on commit 3ebf595

Please sign in to comment.