Created
September 2, 2014 21:19
-
-
Save kevints/302f9fa1d5bd2697f1b7 to your computer and use it in GitHub Desktop.
MVP of twitter.common.application+guice+jetty+shiro+jersey
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.apache.aurora.scheduler.app; | |
import java.util.Arrays; | |
import javax.inject.Inject; | |
import javax.inject.Named; | |
import javax.inject.Singleton; | |
import javax.servlet.ServletContext; | |
import javax.servlet.ServletContextEvent; | |
import javax.ws.rs.DefaultValue; | |
import javax.ws.rs.GET; | |
import javax.ws.rs.Path; | |
import javax.ws.rs.Produces; | |
import javax.ws.rs.QueryParam; | |
import javax.ws.rs.core.MediaType; | |
import com.google.inject.AbstractModule; | |
import com.google.inject.Injector; | |
import com.google.inject.Module; | |
import com.google.inject.Provides; | |
import com.google.inject.name.Names; | |
import com.google.inject.servlet.GuiceFilter; | |
import com.google.inject.servlet.GuiceServletContextListener; | |
import com.sun.jersey.guice.JerseyServletModule; | |
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; | |
import com.twitter.common.application.AbstractApplication; | |
import com.twitter.common.application.AppLauncher; | |
import com.twitter.common.args.Arg; | |
import com.twitter.common.args.ArgFilters; | |
import com.twitter.common.args.CmdLine; | |
import org.apache.shiro.SecurityUtils; | |
import org.apache.shiro.guice.web.ShiroWebModule; | |
import org.apache.shiro.realm.text.IniRealm; | |
import org.mortbay.jetty.Handler; | |
import org.mortbay.jetty.Server; | |
import org.mortbay.jetty.servlet.Context; | |
import org.mortbay.jetty.webapp.WebAppContext; | |
import static java.util.Objects.requireNonNull; | |
/** | |
* Created by ksweeney on 8/29/14. | |
*/ | |
public class SecureSchedulerMain extends AbstractApplication { | |
@CmdLine(name = "exclamation", help = "What to exclaim") | |
private static final Arg<String> EXCLAMATION = Arg.create("!"); | |
public static void main(String... args) throws Exception { | |
AppLauncher.launch( | |
SecureSchedulerMain.class, | |
ArgFilters.selectClass(SecureSchedulerMain.class), | |
args); | |
} | |
@Inject | |
private Server server; | |
@Override | |
public void run() { | |
try { | |
server.start(); | |
server.join(); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
@Override | |
public Iterable<? extends Module> getModules() { | |
return Arrays.asList(new AbstractModule() { | |
@Override | |
protected void configure() { | |
bind(GuiceServletContextListener.class).to(AuroraServletContextListener.class); | |
bind(AuroraServletContextListener.class).in(Singleton.class); | |
bind(Handler.class).to(WebAppContext.class); | |
bind(Handler.class).to(WebAppContext.class); | |
} | |
@Provides | |
private WebAppContext provideWebAppContext(GuiceServletContextListener listener) { | |
WebAppContext webAppContext = new WebAppContext(); | |
webAppContext.setContextPath("/"); | |
webAppContext.setResourceBase("src/main/webapp"); | |
webAppContext.addFilter(GuiceFilter.class, "/*", Context.NO_SESSIONS); | |
webAppContext.addEventListener(listener); | |
return webAppContext; | |
} | |
@Provides | |
@Singleton | |
private Server provideServer(Handler handler) { | |
Server server = new Server(7070); | |
server.addHandler(handler); | |
return server; | |
} | |
}); | |
} | |
static class AuroraServletContextListener extends GuiceServletContextListener { | |
private final Injector parentInjector; | |
private ServletContext servletContext; | |
@Inject | |
AuroraServletContextListener(Injector parentInjector) { | |
this.parentInjector = requireNonNull(parentInjector); | |
} | |
@Override | |
public void contextInitialized(ServletContextEvent event) { | |
this.servletContext = event.getServletContext(); | |
super.contextInitialized(event); | |
} | |
@Override | |
protected Injector getInjector() { | |
return parentInjector.createChildInjector( | |
new ShiroWebModule(servletContext) { | |
@Override | |
protected void configureShiroWeb() { | |
// https://gist.github.com/kevints/5999b5379890c0b5dc6f | |
bindRealm().toInstance(new IniRealm("classpath:shiro.ini")); | |
addFilterChain("/api/**", AUTHC_BASIC); | |
addFilterChain("/**", ANON); | |
} | |
}, | |
ShiroWebModule.guiceFilterModule(), | |
new JerseyServletModule() { | |
@Override | |
protected void configureServlets() { | |
serve("/api/*").with(GuiceContainer.class); | |
// GuiceContainer needs a handle to this Injector, not to the parent injector. | |
// bind here promotes it to an explicit binding, which causes it to be created in | |
// this injector rather than the parent injector. For context see | |
// https://groups.google.com/forum/#!topic/google-guice/Q592mWKTS1Q | |
bind(GuiceContainer.class); | |
bindConstant().annotatedWith(Names.named("serverName")).to("aurora"); | |
bind(HelloResource.class); | |
} | |
} | |
); | |
} | |
@Path("hello") | |
public static class HelloResource { | |
private final String serverName; | |
@Inject | |
HelloResource(@Named("serverName") String serverName) { | |
this.serverName = requireNonNull(serverName); | |
} | |
@GET | |
@Produces(MediaType.TEXT_PLAIN) | |
public String getHello( | |
@QueryParam("who") @DefaultValue("world") String who) { | |
return String.format( | |
"Hello to %s from %s via %s%s\n", | |
who, | |
SecurityUtils.getSubject().getPrincipal(), | |
serverName, | |
EXCLAMATION.get()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment