I have a SpringMVC web applicatioin, I set the value for a Object property in HandlerInterceptorAdapter:
public class SpringMVCFilter extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Interceptor.ss = "foo"; // it's a static field
return super.preHandle(request, response, handler);
}
...more code hidden
}
Then, I getting the value in the MySQL QueryInterceptor:
public class Interceptor implements QueryInterceptor {
public static String ss = null;
#Override
public <T extends Resultset> T postProcess(Supplier<String> sql, Query interceptedQuery, T originalResultSet, ServerSession serverSession) {
System.out.println(ss); // I have set the value for 'ss' before
return null;
}
...more code hidden
}
ss is obviously a static variable, and I have assigned it a value, why can't I get the value in QueryInterceptor, they are in the some thread, but the ss always show null, the execution order is assigned first.
enviroment:
mysql:mysql-connector-java:8.0.13
spring boot 2.0.2.RELEASE
Related
I have a java servlet that sets a session variable and calls an starts a thread class.I implement is a follows
#WebServlet("/ExportLogs")
public class ExportLogs extends HttpServlet
{
public void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException,IOException
{
Integer completePercent = new Integer(10);
request.getSession().setAttribute("CompletionStatus" , completePercent);
LogExportingProcess export = new LogExportingProcess();
export.start();
}
}
and i have the thread class that performs a long process as follows ;
class LogExportingProcess extends Thread
{
public void run()
{
//i want to change the value of the percent complete variable in here.
}
}
Now i want to change the value of the completePercent value inside the LogExportingProcess class.How can i achieve it.
You will have to pass the Session object while creating LogExportingProcess
class LogExportingProcess extends Thread
{
private HttpSession session;
public LogExportingProcess(HttpSession session) {
this.session = session;
}
public void run()
{
session.setAttribute("CompletionStatus" , completePercent);
}
}
and one change in ExportLogs class
LogExportingProcess export = new LogExportingProcess(request.getSession());
Integer is not mutable. AtomicInteger would be a nice substitute.
#WebServlet("/ExportLogs")
public class ExportLogs extends HttpServlet
{
public void doGet( final HttpServletRequest request , final HttpServletResponse response ) throws ServletException,IOException
{
final AtomicInteger completePercent = new AtomicInteger(10);
request.getSession().setAttribute("CompletionStatus" , completePercent);
final LogExportingProcess export = new LogExportingProcess( completePercent );
export.start();
}
}
class LogExportingProcess extends Thread
{
final AtomicInteger completePercent;
public LogExportingProcess( final AtomicInteger completePercent )
{
this.completePercent = completePercent;
}
public void run()
{
completePercent.set( 80 ); //80% complete, substitute with real code
}
}
This is preferrable IMHO over holding a reference to the HttpSession object as suggested by Yogesh Badke, since the HttpSession can be garbage collected normally upon timeout, and AtomicInteger increases encapsulation by only sharing a percentage instead of the entire session information.
I have the following code to be unit tested:
public void foo() {
Entity entity = //...
persistence.save(entity);
entity.setDate(new Date());
persistence.save(entity);
}
I would like to verify that on the first invocation of persistence.save entity.getDate() returns null.
Therefore I'm unable to use Mockito.verify(/*...*/) because at that time the method foo already completed and entity.setDate(Date) was called.
So I think I need to do verifications of invocations already at the time the invocations happen. How do I do this using Mockito?
I created the following Answer implementation:
public class CapturingAnswer<T, R> implements Answer<T> {
private final Function<InvocationOnMock, R> capturingFunction;
private final List<R> capturedValues = new ArrayList<R>();
public CapturingAnswer(final Function<InvocationOnMock, R> capturingFunction) {
super();
this.capturingFunction = capturingFunction;
}
#Override
public T answer(final InvocationOnMock invocation) throws Throwable {
capturedValues.add(capturingFunction.apply(invocation));
return null;
}
public List<R> getCapturedValues() {
return Collections.unmodifiableList(capturedValues);
}
}
This answer captures properties of the invocations being made. The capturedValues can then be used for simple assertions. The implementation uses Java 8 API. If that is not available one would need to use an interface that is able to convert the InvocationOnMock to the captured value. The usage in the testcase is like this:
#Test
public void testSomething() {
CapturingAnswer<Void,Date> captureDates = new CapturingAnswer<>(this::getEntityDate)
Mockito.doAnswer(captureDates).when(persistence).save(Mockito.any(Entity.class));
service.foo();
Assert.assertNull(captureDates.getCapturedValues().get(0));
}
private Date getEntityDate(InvocationOnMock invocation) {
Entity entity = (Entity)invocation.getArguments()[0];
return entity.getDate();
}
The capturing that is done by the presented Answer implementation can't be achieved with Mockitos ArgumentCaptor because this is only used after the invocation of the method under test.
In my original comment, this was the answer I had in mind.
The class to be mocked:
class MockedClass{
void save(SomeBean sb){
//doStuff
}
}
The class we'll need to verify the Date object is null.
class SomeBean{
Date date;
Date getDate(){return date;}
void setDate(Date date){this.date=date;}
}
The class under test:
class TestClass{
MockedClass mc;
TestClass(MockedClass mc){this.mc = mc;}
void doWork(){
SomeBean sb = new SomeBean();
mc.save(sb);
sb.setDate(new Date());
mc.save(sb);
}
}
And the test case:
#Test
public void testAnswer(){
MockedClass mc = Mockito.mock(MockedClass.class);
Mockito.doAnswer(new Answer<Void>(){
boolean checkDate = true;
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
SomeBean sb = (SomeBean) invocation.getArguments()[0];
if(checkDate && sb.getDate() != null){
throw new NullPointerException(); //Or a more meaningful exception
}
checkDate = false;
return null;
}}).when(mc).save(Mockito.any(SomeBean.class));;
TestClass tc = new TestClass(mc);
tc.doWork();
}
The first time through this Answer (The term I should have used in my original comment), this will throw an exception and fail the test case if date is not null. The second time through, checkDate will be false, so the check will not be performed.
I'm trying to implement a simple autentication system in Play Framework 2.4.x using Deadbolt 2.
I've followed this guide written by Chaloner and I've implemented my deadbolt handler as you can see here:
public class MyDeadboltHandler extends AbstractDeadboltHandler {
public F.Promise<Optional<Result>> beforeAuthCheck(Http.Context context) {
// returning null means that everything is OK. Return a real result if you want a redirect to a login page or
// somewhere else
return F.Promise.promise(Optional::empty);
}
public F.Promise<Optional<Subject>> getSubject(Http.Context context) {
// in a real application, the user name would probably be in the session following a login process
User user = new User("MyUser", "my.email#info.com");
return F.Promise.promise(() -> Optional.ofNullable(user));
}
public F.Promise<Optional<DynamicResourceHandler>> getDynamicResourceHandler(Http.Context context) {
return F.Promise.promise(() -> Optional.of(new MyDynamicResourceHandler()));
}
#Override
public F.Promise<Result> onAuthFailure(final Http.Context context, final String content) {
// you can return any result from here - forbidden, etc
return F.Promise.promise(() -> Controller.redirect(routes.Application.index()));
}
}
My main controller is this:
public class Application extends Controller {
public Result index() {
return ok(index.render());
}
#SubjectPresent
public Result denyAccess(){
return ok(notAllowed.render());
}
public Result permitAccess(){
return ok(allowed.render());
}
public Result errorPage(){
return ok(errorPage.render());
}
}
The problem appears when I try to access the page rendered by the action denyAccess. In this case I get a NullPointerException on page without a stack trace I can read, as you can see in the following image.
It seems that the method onAuthFailure is never invoked even when I try to access the controller denyAccess.
You can see the complete project here on my github page, it's very short and I think it can help you to understand the problem.
Thank you for your help.
The problem lies in your implementation of HandlerCache:
#Singleton
public class MyHandlerCache implements HandlerCache {
private final Map<String, DeadboltHandler> handlers = new HashMap<>();
public MyHandlerCache() {
handlers.put("DEFAULT_KEY", new MyDeadboltHandler());
}
#Override
public DeadboltHandler apply(final String key) {
return handlers.get(key);
}
#Override
public DeadboltHandler get() {
return handlers.get("DEFAULT_KEY");
}
}
By default, the default handler key name is defined by be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY but in MyHandlerCache you use "DEFAULT_KEY". However, when this method is called:
public DeadboltHandler apply(final String key) {
return handlers.get(key);
}
it will receive be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY as a key and return null.
I'll make sure this is logged better and made clear in the documentation. To fix your implementation, replace "DEFAULT_KEY" with be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY:
#Singleton
public class MyHandlerCache implements HandlerCache {
private final Map<String, DeadboltHandler> handlers = new HashMap<>();
public MyHandlerCache() {
handlers.put(ConfigKeys.DEFAULT_HANDLER_KEY, new MyDeadboltHandler());
}
#Override
public DeadboltHandler apply(final String key) {
return handlers.get(key);
}
#Override
public DeadboltHandler get() {
return handlers.get(ConfigKeys.DEFAULT_HANDLER_KEY);
}
}
I'm getting an error from PowerMock when running the following:
whenNew(Socket.class).withAnyArguments().thenReturn(server).thenCallRealMethod();
The error is:
You probably stored a reference to OngoingStubbing returned by when() and
called stubbing methods like thenReturn() on this reference more than once.
Examples of correct usage:
when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);
when(mock.isOk()).thenReturn(true, false).thenThrow(exception);
Any idea how I can return my mock object on the first new and afterwards call the default constructor?
I don't know about any built-in solution, but try this one, it's supposed to work:
whenNew(Socket.class).withAnyArguments().thenAnswer(new Answer<Object>() {
boolean firstCall;
#Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
if (firstCall) {
firstCall = false;
return server;
}
return invocationOnMock.callRealMethod();
}
});
With thenAnswer you can implement any logic for mocking a method inside an Answer.
So, if you need such a behavior often, I would suggest you encapsulating it into a class like this:
class MockOnlyFirstCall<T> implements Answer<T> {
private final T firstCallResult;
private boolean firstCall = true;
public MockOnlyFirstCall(T firstCallResult) {
this.firstCallResult = firstCallResult;
}
#Override
public T answer(InvocationOnMock invocationOnMock) throws Throwable {
if (firstCall) {
firstCall = false;
return firstCallResult;
}
return invocationOnMock.callRealMethod();
}
}
Then you could just do
whenNew(Socket.class)
.withAnyArguments()
.thenAnswer(new MockOnlyFirstCall<>(server));
I am new to java generics and below is the code that has created a confusion for me to pass generics class as an argument to the method.
I have created an android project where i have used Volley library to handle server calls.Below is the code
Advanced Connection Util : this class returns the JacksonRequest object
public class AdvancedConnectionUtil<T> {
private String requestType;
private ServerListener listener;
public AdvancedConnectionUtil(String requestType , ServerListener<T> listener){
this.listener = listener;
this.requestType = requestType;
}
public JacksonRequest getRequest(){
//This gives compile error while while passing DataList.class in the argument
return new JacksonRequest<T>(Request.Method.GET, HttpRequestConstant.JACKSON_FETCH, null ,DataList.class, new Response.Listener<T>() {
#Override
public void onResponse(T response) {
listener.onDataReceived(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
listener.onErrorReceived(error.getMessage());
}
});
}
public interface ServerListener<T> {
public void onDataReceived(T data);
public void onErrorReceived(String errorMsg);
}
}
Custom JacksonRequest class : this class handles the server call and the success call backs
public class JacksonRequest<T> extends JsonRequest<T> {
private Class<T> responseType;
/**
* Creates a new request.
* #param method the HTTP method to use
* #param url URL to fetch the JSON from
* #param requestData A {#link Object} to post and convert into json as the request. Null is allowed and indicates no parameters will be posted along with request.
* #param responseType
* #param listener Listener to receive the JSON response
* #param errorListener Error listener, or null to ignore errors.
*/
public JacksonRequest(int method, String url, Object requestData, Class<T> responseType, Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(method, url, (requestData == null) ? null : Mapper.string(requestData), listener, errorListener);
this.responseType = responseType;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return super.getHeaders();
}
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(Mapper.objectOrThrow(json, responseType), HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
}
Here is My activity class that creates a request and pass it to other method to make a server call
public class CustomJacksonRequestActivity extends SuperActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
showProgressBar();
JacksonRequest jacksonRequest = new AdvancedConnectionUtil<DataList>(null, httpListener).getRequest();
//This commented code works fine when i create a request this way
/* JacksonRequest<DataList> jacksonRequest = new JacksonRequest<DataList>(Request.Method.GET, HttpRequestConstant.JACKSON_FETCH, null, DataList.class, new Response.Listener<DataList>() {
#Override
public void onResponse(DataList response) {
hideProgressBar();
Log.e("ANSH", "onResponse : " + response.getPicture());
// fillListWithIndex(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideProgressBar();
Log.e("ANSH", "onErrorResponse : " + error.getLocalizedMessage());
}
});*/
onExecute(jacksonRequest);
}
#Override
protected void internetAvailable() {
}
#Override
public void setTitle(CharSequence title) {
super.setTitle("CustomJacksonActivity");
}
private AdvancedConnectionUtil.ServerListener httpListener = new AdvancedConnectionUtil.ServerListener<DataList>() {
#Override
public void onDataReceived(DataList data) {
Log.e("ANSH", "onResponse : " + data.getPicture());
}
#Override
public void onErrorReceived(String errorMsg) {
Log.e("ANSH", "onResponse : " + errorMsg);
}
};
Now the problem is i am not able to pass DataList.class(This is the response model class) as a parameter in the constructor of JacksonRequest Class inside the getRequest method of AdvancedConnectionUtil class though i am able to do that when i was creating the request object in the activity(see the commented code in the activity).
How can i pass the DataList.class to the constructor of JacsonRequest?
The updated code is in git hub now
github link to the project
Your code is a little confusing (you could do with a simpler example), but I'll give it a shot...
The JacksonRequest class takes one generic type parameter <T> and the type of 4th constructor parameter references this type: , Class<T> responseType,. That means that when an instance of JacksonRequest is instantiated (with T being a real type), the 4th parameter passed must guarantee to be of type T.class.
When you call the constructor...
return new JacksonRequest<T>(Request.Method.GET, blah, null ,DataList.class, ...
... you are calling it with a generic type argument <T>. The compiler must always be able to match generic type arguments with generic type parameters, but with the 4th parameter you are asking it to match T with DataClass. Since the compiler does not know what T is (or more precisely, it cannot guarantee that when it is instantiated, T will actually be DataClass), it gives an error.
Generally speaking, you cannot mix generic type parameters and real type values - you must consistently choose one or the other. There are options which allow you to specify that a generic type parameter will derive from a class or implement an interface (<T super DataClass> or <T extends DataClass>, but it's a bit much to explain here.
The problem with your code is that :
Your JacksonRequest<T> is declared to take a listener that must be parameterized on the same type as your responseType
However with your AdvancedConnectionUtil<T>.getRequest(...), there is no guarantee that the JacksonRequest created will meet the above requirement. Because you can always write code like:
new AdvancedConnectionUtil<String> (null, httpListener).getRequest();
So the parameter you passed into the constructor of JacksonRequest will be a DataList.class (of type Class<DataList>) and a listener of type Listener<String>
Sadly there is no way to do T.class in Java, although that indeed feels like what you need. Usually in such cases we will declare the AdvancedConnectionUtil as:
class AdvancedConnectionUtil<T> {
private final Class<T> responseType;
private final ServerListener<T> serverListener;
private final String requestType;
public AdvancedConnectionUtil (String requestType , Class<T> responseType, ServerListener<T> listener) {
this.requestType = requestType;
this.responseType = responseType;
this.serverListener = listener;
}
public JacksonRequest<T> getRequest(){
return new JacksonRequest<T>(0, "", null ,responseType, new Response.Listener<T>(){
...
}
}
You need pass your responseType of Class<T> into AdvancedConnectionUtil and keep it as a member field. This way the AdvancedConnectionUtil instance, when created, is strictly limited to provide JacksonRequest bounded to a specific response type.
You could in theory declare your getRequest method as getRequest(Class<T> responseType). But your AdvancedConnectionUtil does not seem to gain anything from that