Sorry for my english.... May be someone help me find information about using batch job with role-based security in glassfish server?
When I invoke the method from EJB :
#Override
#RolesAllowed({"root_role", "admin_role", "user_role"})
public void execute() {
BatchRuntime.getJobOperator().start(STATISTIC_JOB_NAME, new Properties());
}
I get exception like this:
javax.ejb.AccessLocalException: Client not authorized for this invocation
My job class:
#Dependent
#Named(value = "StatisticJob")
public class StatisticJob extends AbstractBatchlet {
#EJB
private StatisticFacadeLocal sfl;
#Override
public String process() throws Exception {
System.out.println("StatisticJob.process()");
List<StatisticPortEntity> spes = sfl.findAll();
if (spes != null && !spes.isEmpty()) {
for (StatisticPortEntity spe : spes) {
System.out.println(spe);
}
} else {
return "Statistic list is empty.";
}
return "StatisticJob.proccess is done.";
}
}
How use role-based security with batch?
Thank's!
Related
I would like to write xunit test case of below method. Could you please suggest alternate design so i can write xunit test case with minimum change in my current project.
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = ContextFactory.Current.GetDomain<EmployeeDomain>().GetEmployeeFilterAsync(id,
CurrentUser.CompanyId, filter); // Not able write unit test case , please suggest alternate design.
return View("View", response);
}
}
current design is as follow
public interface IDomain
{
}
public interface IContext
{
D GetDomain<D>() where D : IDomain;
string ConnectionString { get; }
}
public class ApplicationContext : IContext
{
public D GetDomain<D>() where D : IDomain
{
return (D)Activator.CreateInstance(typeof(D));
}
public string ConnectionString
{
get
{
return "DatabaseConnection";
}
}
}
public class ContextFactory
{
private static IContext _context;
public static IContext Current
{
get
{
return _context;
}
}
public static void Register(IContext context)
{
_context = context;
}
}
//var response = ContextFactory.Current.GetDomain**< EmployeeDomain>**().GetEmployeeFilterAsync(id,
CompanyId, filter);
This line serve purpose to call specific class method i.e GetEmployeeFilterAsync from EmployeeDomain. Although it is very handy and widely used in our application but due to design issue i am not able to write unit
test case.
Could you please suggest design so with the minimum change we can write unit test case.
Don't use the Service Locator anti-pattern, use Constructor Injection instead. I can't tell what AssetDomain is from the OP, but it seems as though it's the dependency that matters. Inject it into the class:
public class ProbablySomeController
{
public ProbablySomeController(AssetDomain assetDomain)
{
AssetDomain = assetDomain;
}
public AssetDomain AssetDomain { get; }
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = AssetDomain.GetAssetFilterAsync(id, CurrentUser.CompanyId, filter);
return View("View", response);
}
}
}
Assuming that AssetDomain is a polymorphic type, you can now write a test and inject a Test Double:
[Fact]
public void MyTest()
{
var testDouble = new AssetDomainTestDouble();
var sut = new ProbablySomeController(testDouble);
var actual = sut.Index(42, AssetFilterType.All);
// Put assertions here
}
step1 : Required library
step 2 : When the application starts , register required domain like
protected void Application_Start()
UnityConfig.RegisterComponents();
Step 3: create one static class and register all your domain
example
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
Initialize domain which will injected in controller
container.RegisterType<IPricingDomain, PricingDomain>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
step 4 :
so you can inject respective interface in constructor
in controller file.
goal : get rid of below any pattern in your project.
and start writing unit test cases.
I have written a Reactive API using Spring WebFlux version 2.3.0.RELEASE having reactor-netty version 0.9.10. As part of the API's SLA, I want to timeout the request if the Server takes more than the stipulated configured WriteTimeout.
Sharing the code snipped below where I have implemented a customizer for NettyReactiveWebServerFactory.
#Bean
public WebServerFactoryCustomizer serverFactoryCustomizer() {
return new NettyTimeoutCustomizer();
}
class NettyTimeoutCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {
#Override
public void customize(NettyReactiveWebServerFactory factory) {
int connectionTimeout = 1000;
int writeTimeout = 1;
factory.addServerCustomizers(server -> server.tcpConfiguration(tcp ->
tcp.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeout)
.doOnConnection(connection ->
connection.addHandlerLast(new WriteTimeoutHandler(writeTimeout)))));
}
}
In spite of the Customizer, the WriteTimeout is Not Working for the API.
Instead of defining a WebServerFactoryCustomizer bean, create a bean of NettyReactiveWebServerFactory to override Spring's auto-configuration.
#Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory();
webServerFactory.addServerCustomizers(new MyCustomizer());
return webServerFactory;
}
Now the MyCustomizer will look something like this:
public class MyCustomizer implements NettyServerCustomizer {
#Override
public HttpServer apply(HttpServer httpServer) {
return httpServer.tcpConfiguration(tcpServer -> tcpServer.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
.bootstrap(serverBootstrap -> serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
#Override
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast("writeTimeoutHandler", new WriteTimeoutHandler(1));
}
}))
);
}
}
This is the way suggested in the official API doc
In a JAX-RS application, some of my resources must be filtered depending on which roles the signed-in user has been assigned to. I'm trying to accomplish this using security annotations (#RolesAllowed, #DenyAll and #PermitAll).
This is what I'm looking for:
public class MyEntity {
public String getPublicString() {
...
}
#RolesAllowed("secretRole")
public String getSecretString() {
...
}
}
#Path("/myResource")
public MyResource {
#GET #Path("/{id}")
public MyEntity get(#PathParam("id") int id) {
...
}
}
Now, everyone (anonymous and logged-in users) can GET MyResource and retrieve MyEntity (per id), but for users in role secretRole, I'd like to see the output (here serialized as JSON):
{
"publicString": "...",
"secretString": "..."
}
And other users (either anonymous or otherwise users not acting on role secretRole) should see just:
{
"publicString": "..."
}
I know Jersey has entity filtering (and an implementation that filters based in security roles).
Unfortunately Liberty (Apache CXF based) has no such feature.
What have I done so far?
Since my solution deals primarily with JSON - using Jackson - I did some work based on Jackson's BeanSerializerModifier. Forget BeanSerializerModifier: it gets called only once per bean type (so the first user defines which properties get serialized for all other users - no, thanks).
Just found another Jackson concept that is applied each time a bean is about to be serialized: PropertyFilter and JsonFilter.
It kind of works, the implementation being very simple:
new SimpleBeanPropertyFilter() {
#Override
protected boolean include(BeanPropertyWriter writer) {
return include((PropertyWriter)writer);
}
#Override
protected boolean include(PropertyWriter writer) {
if (writer.findAnnotation(DenyAll.class) != null) {
return false;
}
RolesAllowed rolesAllowed = writer.findAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
boolean anyMatch = Arrays.stream(rolesAllowed.value())
.anyMatch(role -> securityContext.isUserInRole(role));
if (!anyMatch) {
return false;
}
}
return true;
}
}
And what's missing?
The Achilles' heel in above implementation is the securityContext reference (expecting an instance of SecurityContext).
I couldn't find means to get hold of a reference to the current security context.
Usually securityContext is #Context injected - either as a method parameter or as a field parameter. None of this is available to a BeanSerializerModifier.
I've managed to inject #Context SecurityContext (both by field or by constructor parameter); it happens to be a ThreadLocalSecurityContext in Liberty. BUT its method isUserInRole only works for the first request (when the ObjectMapper is created); then the reference gets stale and any other invocation throws NPE (inside isUserInRole method; the securityContext is still a valid java object reference; though referencing a stale object).
What are my constraints?
Jersey is not an option for me. I'm bound to Liberty (which is Apache CXF based).
I'm already used to Jackson, but it is not a must. JSON and REST are.
EDIT
HOLD ON: I thought the problem was the securityContext, but perhaps it is not the culprit. In time: I've managed to inject #Context SecurityContext (both by field or by constructor parameter); it happens to be a ThreadLocalSecurityContext, so I suppose it will get the actual principal from threadlocal storage.
BUT now I realized that BeanSerializerModifier#changeProperties gets called just once (for each bean), then the list of changed properties gets reused! I'll look closely at the Jackson specs; maybe I'll switch to JSON-B, as pointed by #Andy McCright (if its PropertyVisibilityStrategy doesn't also cache the result).
EDIT 2
Previous implementation with BeanSerializerModifier:
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
return beanProperties.stream()
.filter(property -> {
if (property.findAnnotation(DenyAll.class) != null) {
return false;
}
RolesAllowed rolesAllowed = property.findAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
boolean anyMatch = Arrays.stream(rolesAllowed.value())
.anyMatch(role -> securityContext.isUserInRole(role));
if (!anyMatch) {
return false;
}
}
return true;
})
.collect(toList());
}
I've managed to handle an instance of SecurityContext over a ThreadLocal. To this end I've implemented a ContainerRequestFilter:
static final ThreadLocal<SecurityContext> tlSecurityContext = new ThreadLocal<>();
#Provider
public static class SecurityContextSavingRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
tlSecurityContext.set(requestContext.getSecurityContext());
}
}
Then tlSecurityContext.get() can be used as the current SecurityContext.
I don't know, however, if this is invalid or otherwise not recommended by JAX-RS spec.
Beyond this I've also switched to JSON-B (from Jackson) because:
it has better integration with Liberty (both server and client JAX-RS) by means of feature jsonb-1.0;
property filtering is less verbose (than Jackson's PropertyFilter), although less powerful too.
Full solution follows (with comments):
A ContextResolver<Jsonb> to configure Jsonb:
#Provider
public class JsonbConfigContextResolver implements ContextResolver<Jsonb> {
#Override
public Jsonb getContext(Class<?> type) {
return JsonbBuilder.newBuilder().withConfig(getConfig()).build();
}
private JsonbConfig getConfig() {
return new JsonbConfig().withPropertyVisibilityStrategy(new SecurityPropertyVisibilityStrategy());
}
}
A PropertyVisibilityStrategy to implement filtering proper:
public class SecurityPropertyVisibilityStrategy implements PropertyVisibilityStrategy {
#Override
public boolean isVisible(Field field) {
return false;
}
#Override
public boolean isVisible(Method method) {
if (method.getAnnotation(DenyAll.class) != null) {
return false;
}
RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
boolean anyMatch = Arrays.stream(rolesAllowed.value())
.anyMatch(role -> isUserInRole(role));
if (!anyMatch) {
return false;
}
}
return true;
}
And finally the ThreadLocal hack itself:
private boolean isUserInRole(String role) {
return securityContext.get().isUserInRole(role);
}
private static final ThreadLocal<SecurityContext> securityContext = new ThreadLocal<>();
#Provider
public static class SecurityContextSavingRequestFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
securityContext.set(requestContext.getSecurityContext());
}
}
}
I am having one Application based on XamarinForms.
One background service I have created in Android project and that service would like to send data to ContentPage(which is in PCL) which is displayed to user.
How could I pass data to ContentPage(From xx.Droid project to PCL)?
One solution is:
To Create class in PCL with static variable(e.g. var TEMP_VAR), which will be accessed from xxx.Droid project.
Update value of that static variable(TEMP_VAR) from the service class from the xxx.Droid project.
Need to create Notifier on that static variable(TEMP_VAR)
Update the content page using MessageCenter Mechanism if require.
If there is any better solution, could you please provide me?
This can be achieved using the concept of C#
Dependency service
Event
Need to have 4 classes for such an implementation:
Interface in PCL(e.g. CurrentLocationService.cs) with event handlers defined in it.
namespace NAMESPACE
{
public interface CurrentLocationService
{
void start();
event EventHandler<PositionEventArgs> positionChanged;
}
}
Implementation of interface of PCL in xxx.Droid project (e.g. CurrentLocationService_Android.cs) using Dependency service
class CurrentLocationService_Android : CurrentLocationService
{
public static CurrentLocationService_Android mySelf;
public event EventHandler<PositionEventArgs> positionChanged;
public void start()
{
mySelf = this;
Forms.Context.StartService(new Intent(Forms.Context, typeof(MyService)));
}
public void receivedNewPosition(CustomPosition pos)
{
positionChanged(this, new PositionEventArgs(pos));
}
}
ContentPage in PCL - which will have object of implementation of interface.
Object can be obtained by
public CurrentLocationService LocationService
{
get
{
if(currentLocationService == null)
{
currentLocationService = DependencyService.Get<CurrentLocationService>();
currentLocationService.positionChanged += OnPositionChange;
}
return currentLocationService;
}
}
private void OnPositionChange(object sender, PositionEventArgs e)
{
Debug.WriteLine("Got the update in ContentPage from service ");
}
Background service in xxx.Droid project. This service will have reference of implementation of dependency service CurrentLocationService.cs
[Service]
public class MyService : Service
{
public string TAG = "MyService";
public override IBinder OnBind(Intent intent)
{
throw new NotImplementedException();
}
public override StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)
{
Log.Debug(TAG, TAG + " started");
doWork();
return StartCommandResult.Sticky;
}
public void doWork()
{
var t = new Thread(
() =>
{
Log.Debug(TAG, "Doing work");
Thread.Sleep(10000);
Log.Debug(TAG, "Work completed");
if(CurrentLocationService_Android.mySelf != null)
{
CustomPosition pos = new CustomPosition();
pos.update = "Finally value is updated";
CurrentLocationService_Android.mySelf.receivedNewPosition(pos);
}
StopSelf();
});
t.Start();
}
}
Note : PositionEventArgs class need to be created as per usage to pass on data between service and ContentPage.
This works for me like charm.
Hope so this would be helpful to you.
I am preparing a ReSTful service which I would like to have documented using RAML (and perhaps Swagger as well), but it seems that I cannot implement both JAX-RS and RAML in the same application at the same time.
I have created an Application class for JAX-RS as follows:
public class Application extends javax.ws.rs.core.Application {
#Override
public Set<Class<?>> getClasses() {
// Use the reflections library to scan the current package tree for
// classes annotated with javax.ws.rs.Path and add them to the JAX-RS
// application
Reflections reflections = new Reflections(this.getClass().getPackage().getName());
return reflections.getTypesAnnotatedWith(Path.class);
}
}
I attach the JAX-RS Application object as follows:
Component component = new Component();
Server server = new Server(Protocol.HTTP, PORT);
component.getServers().add(server);
JaxRsApplication jaxRsApplication = new JaxRsApplication(component.getContext().createChildContext());
jaxRsApplication.add(new Application());
jaxRsApplication.setObjectFactory(objectFactory);
component.getDefaultHost().attach("/rest", jaxRsApplication);
And I would also like to implement the RAML extension, but it looks like it is tied to the Restlet Router and having it's own Application class. Is there a way to combine the two?
Indeed the RAML extension of Restlet isn't designed to be used within JAXRS application. That said you can define a resource that provide the RAML content based on classes ApplicationIntrospector of Restlet and RamlEmitter of RAML parser, as described below:
public class RamlResource {
private Definition definition;
#Path("/raml")
#GET
public String getRaml() {
return new RamlEmitter().dump(RamlTranslator
.getRaml(getDefinition()));
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (RamlResource.class) {
definition = ApplicationIntrospector.getDefinition(
Application.getCurrent(),
new Reference("/"), null, false);
}
}
return definition;
}
}
It's the way the RAML extension of Restlet works. You could also use such an approach for Swagger but be careful since Swagger 1.2 requires several resources (a main and several sub ones with each categories). It's not the case anymore for Swagger 2.
You can notice that there is a JAX-RS support for Swagger in the extension org.restlet.ext.swagger.
----- Edited
Perhaps can you make a try with this class that corresponds to a port of the class JaxRsApplicationSwaggerSpecificationRestlet to RAML. It's based on the class JaxRsIntrospector which seems relevant for JAX-RS application:
public class JaxRsApplicationRamlSpecificationRestlet extends Restlet {
private Application application;
private String basePath;
private Reference baseRef;
private Definition definition;
public JaxRsApplicationRamlSpecificationRestlet(Application application) {
this(null, application);
}
public JaxRsApplicationRamlSpecificationRestlet(Context context, Application application) {
super(context);
this.application = application;
}
public void attach(Router router) {
attach(router, "/api-docs");
}
public void attach(Router router, String path) {
router.attach(path, this);
router.attach(path + "/{resource}", this);
}
public Representation getApiDeclaration() {
Raml raml = RamlTranslator.getRaml(
getDefinition());
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try {
return new StringRepresentation(
mapper.writeValueAsString(raml),
MediaType.APPLICATION_YAML);
} catch (Exception ex) {
return new StringRepresentation("error");
}
}
public String getBasePath() {
return basePath;
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (JaxRsApplicationRamlSpecificationRestlet.class) {
definition = JaxRsIntrospector.getDefinition(application,
baseRef, false);
}
}
return definition;
}
#Override
public void handle(Request request, Response response) {
super.handle(request, response);
if (Method.GET.equals(request.getMethod())) {
response.setEntity(getApiDeclaration());
} else {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
}
}
public void setApiInboundRoot(Application application) {
this.application = application;
}
public void setApplication(Application application) {
this.application = application;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
// Process basepath and check validity
this.baseRef = basePath != null ? new Reference(basePath) : null;
}
}
You can use this class like this:
JaxRsApplication application
= new JaxRsApplication(component.getContext());
MyApplication app = new MyApplication();
application.add(app);
new JaxRsApplicationRamlSpecificationRestlet(app);
(...)
There is no need for a dedicated resource. Please note that this code is a bit experimental ;-) I could propose it back for a contribution for the extension raml in Restlet...
Hope it helps you,
Thierry