#StackBounty: #reactjs #typescript #spring-boot #material-ui #react-typescript Implement pagination for React Material table

Bounty: 200

I have this Spring Boot endpoint for listing items from database:

import React, { useEffect, useState } from "react";

import clsx from "clsx";
import {
  createStyles,
  lighten,
  makeStyles,
  Theme,
} from "@material-ui/core/styles";
import CircularProgress from "@material-ui/core/CircularProgress";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TablePagination from "@material-ui/core/TablePagination";
import TableRow from "@material-ui/core/TableRow";
import TableSortLabel from "@material-ui/core/TableSortLabel";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import Checkbox from "@material-ui/core/Checkbox";
import IconButton from "@material-ui/core/IconButton";
import Tooltip from "@material-ui/core/Tooltip";
import DeleteIcon from "@material-ui/icons/Delete";
import FilterListIcon from "@material-ui/icons/FilterList";
import axios, { AxiosResponse } from "axios";
import { getTask } from "../../service/merchants";

const baseUrl = "http://185.185.126.15:8080/api";

interface OnboardingTaskDto {
  id?: number;
  name: string;
}

async function getTask(
  page: number,
  size: number
): Promise<AxiosResponse<OnboardingTaskDto[]>> {
  return await axios.get<OnboardingTaskDto[]>(
    `${baseUrl}/management/onboarding/task?page=${page}&size=${size}`
  );
}

interface Data {
  id: number;
  businessName: string;
  title: string;
  status: string;
}

function createData(
    id: number,
    businessName: string,
    title: string,
    status: string
): Data {
  return { id, businessName, title, status };
}

function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
  if (b[orderBy] < a[orderBy]) {
    return -1;
  }
  if (b[orderBy] > a[orderBy]) {
    return 1;
  }
  return 0;
}

type Order = "asc" | "desc";

function getComparator<Key extends keyof any>(
    order: Order,
    orderBy: Key
): (
    a: { [key in Key]: number | string },
    b: { [key in Key]: number | string }
) => number {
  return order === "desc"
      ? (a, b) => descendingComparator(a, b, orderBy)
      : (a, b) => -descendingComparator(a, b, orderBy);
}

function stableSort<T>(array: T[], comparator: (a: T, b: T) => number) {
  const stabilizedThis = array.map((el, index) => [el, index] as [T, number]);
  stabilizedThis.sort((a, b) => {
    const order = comparator(a[0], b[0]);
    if (order !== 0) return order;
    return a[1] - b[1];
  });
  return stabilizedThis.map((el) => el[0]);
}

interface HeadCell {
  disablePadding: boolean;
  id: keyof Data;
  label: string;
  numeric: boolean;
}

const headCells: HeadCell[] = [
  { id: "id", numeric: false, disablePadding: true, label: "id" },
  {
    id: "businessName",
    numeric: true,
    disablePadding: false,
    label: "businessName",
  },
  { id: "title", numeric: true, disablePadding: false, label: "title" },
  { id: "status", numeric: true, disablePadding: false, label: "status" },
];

interface EnhancedTableProps {
  classes: ReturnType<typeof useStyles>;
  numSelected: number;
  onRequestSort: (
      event: React.MouseEvent<unknown>,
      property: keyof Data
  ) => void;
  onSelectAllClick: (event: React.ChangeEvent<HTMLInputElement>) => void;
  order: Order;
  orderBy: string;
  rowCount: number;
}

function EnhancedTableHead(props: EnhancedTableProps) {
  const {
    classes,
    onSelectAllClick,
    order,
    orderBy,
    numSelected,
    rowCount,
    onRequestSort,
  } = props;
  const createSortHandler =
      (property: keyof Data) => (event: React.MouseEvent<unknown>) => {
        onRequestSort(event, property);
      };

  return (
      <TableHead>
        <TableRow>
          <TableCell padding="checkbox">
            <Checkbox
                indeterminate={
                  numSelected > 0 && numSelected < rowCount
                }
                checked={rowCount > 0 && numSelected === rowCount}
                onChange={onSelectAllClick}
                inputProps={{ "aria-label": "select all desserts" }}
            />
          </TableCell>
          {headCells.map((headCell) => (
              <TableCell
                  key={headCell.id}
                  align={headCell.numeric ? "right" : "left"}
                  padding={headCell.disablePadding ? "none" : "normal"}
                  sortDirection={orderBy === headCell.id ? order : false}
              >
                <TableSortLabel
                    active={orderBy === headCell.id}
                    direction={orderBy === headCell.id ? order : "asc"}
                    onClick={createSortHandler(headCell.id)}
                >
                  {headCell.label}
                  {orderBy === headCell.id ? (
                      <span className={classes.visuallyHidden}>
                                    {order === "desc"
                                        ? "sorted descending"
                                        : "sorted ascending"}
                                </span>
                  ) : null}
                </TableSortLabel>
              </TableCell>
          ))}
        </TableRow>
      </TableHead>
  );
}

const useToolbarStyles = makeStyles((theme: Theme) =>
    createStyles({
      root: {
        paddingLeft: theme.spacing(2),
        paddingRight: theme.spacing(1),
      },
      highlight:
          theme.palette.type === "light"
              ? {
                color: theme.palette.secondary.main,
                backgroundColor: lighten(
                    theme.palette.secondary.light,
                    0.85
                ),
              }
              : {
                color: theme.palette.text.primary,
                backgroundColor: theme.palette.secondary.dark,
              },
      title: {
        flex: "1 1 100%",
      },
    })
);

interface EnhancedTableToolbarProps {
  numSelected: number;
  onClick: (e: React.MouseEvent<unknown>) => void;
}

const EnhancedTableToolbar = (props: EnhancedTableToolbarProps) => {
  const classes = useToolbarStyles();
  const { numSelected } = props;

  return (
      <Toolbar
          className={clsx(classes.root, {
            [classes.highlight]: numSelected > 0,
          })}
      >
        {numSelected > 0 ? (
            <Typography
                className={classes.title}
                color="inherit"
                variant="subtitle1"
                component="div"
            >
              {numSelected} selected
            </Typography>
        ) : (
            <Typography
                className={classes.title}
                variant="h6"
                id="tableTitle"
                component="div"
            >
              Customers
            </Typography>
        )}
        {numSelected > 0 ? (
            <Tooltip title="Delete">
              <IconButton aria-label="delete" onClick={props.onClick}>
                <DeleteIcon />
              </IconButton>
            </Tooltip>
        ) : (
            <Tooltip title="Filter list">
              <IconButton aria-label="filter list">
                <FilterListIcon />
              </IconButton>
            </Tooltip>
        )}
      </Toolbar>
  );
};

const useStyles = makeStyles((theme: Theme) =>
    createStyles({
      root: {
        width: "100%",
      },
      paper: {
        width: "100%",
        marginBottom: theme.spacing(2),
      },
      table: {
        minWidth: 750,
      },
      visuallyHidden: {
        border: 0,
        clip: "rect(0 0 0 0)",
        height: 1,
        margin: -1,
        overflow: "hidden",
        padding: 0,
        position: "absolute",
        top: 20,
        width: 1,
      },
    })
);

export default function BusinessCustomersTable() {
  const classes = useStyles();
  const [order, setOrder] = React.useState<Order>("asc");
  const [orderBy, setOrderBy] = React.useState<keyof Data>("businessName");
  const [selected, setSelected] = React.useState<number[]>([]);
  const [page, setPage] = React.useState(0);
  const [rowsPerPage, setRowsPerPage] = React.useState(5);
  const [rows, setRows] = useState<Data[]>([]);
  const [loading, setLoading] = useState(false);

  let updatedState: Data[] = [];

  // TODO - move this to API file
  const apiUrl = "http://185.185.126.15:8080/api/management/onboarding/task";

  useEffect(() => {
    const getData = async () => {
      setLoading(true);

      getTask(1, 100)
          .then((resp) => {
            console.log(resp.data);
          })
          .catch((error) => {
            console.error(error);
          });
      const response = await axios.get(apiUrl, {
        params: { page: 1, size: 100 },
      });
      setLoading(false);

      const objContent: any = response.data.content;

      for (let a = 0; a < objContent.length; a++) {
        updatedState[a] = createData(
            objContent[a].id,
            objContent[a].businessName,
            objContent[a].title,
            objContent[a].status
        );

        setRows([...rows, ...updatedState]);
      }
    };

    getData();
  }, []);

  const handleRequestSort = (
      event: React.MouseEvent<unknown>,
      property: keyof Data
  ) => {
    const isAsc = orderBy === property && order === "asc";
    setOrder(isAsc ? "desc" : "asc");
    setOrderBy(property);
  };

  const handleSelectAllClick = (
      event: React.ChangeEvent<HTMLInputElement>
  ) => {
    if (event.target.checked) {
      const newSelecteds = rows.map((n) => n.id);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  const handleClick = (event: React.MouseEvent<unknown>, id: number) => {
    const selectedIndex = selected.indexOf(id);
    let newSelected: number[] = [];

    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, id);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
          selected.slice(0, selectedIndex),
          selected.slice(selectedIndex + 1)
      );
    }

    setSelected(newSelected);
  };

  const handleChangePage = (event: unknown, newPage: number) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (
      event: React.ChangeEvent<HTMLInputElement>
  ) => {
    setRowsPerPage(parseInt(event.target.value, 10));
    setPage(0);
  };

  const handleDeleteClick = async () => {
    // npm install qs
    var qs = require("qs");

    const response = await axios.delete(apiUrl, {
      params: {
        ids: selected,
      },
      paramsSerializer: (params) => {
        return qs.stringify(params);
      },
    });

    if (response.status === 204) {
      const updatedData = rows.filter(
          (row) => !selected.includes(row.id)
      ); // It'll return all data except selected ones

      setRows(updatedData); // reset rows to display in table.
    }
  };

  const isSelected = (id: number) => selected.indexOf(id) !== -1;

  const emptyRows =
      rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);

  return (
      <div className={classes.root}>
        <Paper className={classes.paper}>
          <EnhancedTableToolbar
              numSelected={selected.length}
              onClick={handleDeleteClick}
          />
          <TableContainer>
            <Table
                className={classes.table}
                aria-labelledby="tableTitle"
                aria-label="enhanced table"
            >
              <EnhancedTableHead
                  classes={classes}
                  numSelected={selected.length}
                  order={order}
                  orderBy={orderBy}
                  onSelectAllClick={handleSelectAllClick}
                  onRequestSort={handleRequestSort}
                  rowCount={rows.length}
              />
              <TableBody>
                {loading ? (
                    <div className="spinerr">
                      <CircularProgress />
                    </div>
                ) : null}
                {stableSort(rows, getComparator(order, orderBy))
                    .slice(
                        page * rowsPerPage,
                        page * rowsPerPage + rowsPerPage
                    )
                    .map((row, index) => {
                      const isItemSelected = isSelected(row.id);
                      const labelId = `enhanced-table-checkbox-${index}`;

                      return (
                          <TableRow
                              hover
                              onClick={(event) =>
                                  handleClick(event, row.id)
                              }
                              role="checkbox"
                              aria-checked={isItemSelected}
                              tabIndex={-1}
                              key={row.businessName}
                              selected={isItemSelected}
                          >
                            <TableCell padding="checkbox">
                              <Checkbox
                                  checked={isItemSelected}
                                  inputProps={{
                                    "aria-labelledby":
                                    labelId,
                                  }}
                              />
                            </TableCell>
                            <TableCell
                                component="th"
                                id={labelId}
                                scope="row"
                                padding="none"
                            >
                              {row.id}
                            </TableCell>
                            <TableCell align="right">
                              {row.businessName}
                            </TableCell>
                            <TableCell align="right">
                              {row.title}
                            </TableCell>
                            <TableCell align="right">
                              {row.status}
                            </TableCell>
                          </TableRow>
                      );
                    })}
                {emptyRows > 0 && (
                    <TableRow style={{ height: 53 * emptyRows }}>
                      <TableCell colSpan={6} />
                    </TableRow>
                )}
              </TableBody>
            </Table>
          </TableContainer>
          <TablePagination
              rowsPerPageOptions={[5, 10, 25]}
              component="div"
              count={rows.length}
              rowsPerPage={rowsPerPage}
              page={page}
              onPageChange={handleChangePage}
              onRowsPerPageChange={handleChangeRowsPerPage}
          />
        </Paper>
      </div>
  );
}

Sandbox: https://stackblitz.com/edit/react-ts-tnpk85?file=Hello.tsx

When data is loaded first time and I switch pages I don’t see additional requests to Back end. Looks like data table rows data is loaded only once. I need to implement a lazy pagination and load current page data when I switch page. Do you know how I can fix this?


Get this bounty!!!

#StackBounty: #java #spring-boot #spring-data-rest Spring Data Rest with @Version from Parent-Entity

Bounty: 250

I set up a @Repository for an Entity with a @Version property and published it via @RepositoryRestResource which was pretty straight forward. The version is transfered to the and from the client in the Http Header as an ETag and it works perfectly.

In my current scenario I have a child Entity which doesn’t have a @Version-Tag itself, instead the @Version-Tag of its parent has to be used. That means, that every change of the child or the parent has to increment the parent version. Also the operation should fail, if the parent version is outdated. For this case EntityManager offers the LockModeType.OPTIMISTIC_FORCE_INCREMENT.

How do I customize Spring Data Rest to implement such behavior? Do I have to implement a @RestController from scratch?

—————– edit —————-

Here is a small example i set up which works for a simple entity

Application.java

@SpringBootApplication
public class Application
{
    public static void main(String[] args)
    {
        SpringApplication.run(Application.class, args);
    }

    @Configuration
    @EnableJpaRepositories
    public static class ServerConfiguration
    {
        private EntityManagerFactory emf;
    
        @Bean
        public EntityManagerFactory entityManagerFactory()
        {
            if (emf == null)
            {
                Map<String, Object> properties = new HashMap<>();
                properties.put(AvailableSettings.CLASSLOADERS, Collections.singleton(Thread.currentThread().getContextClassLoader()));
                emf =  Persistence.createEntityManagerFactory("test", properties);
            }
            return emf;
        }

        @Bean
        public PlatformTransactionManager transactionManager()
        {
            JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactory());
            return transactionManager;
        }
    
        @Bean
        public ShallowEtagHeaderFilter shallowEtagHeaderFilter() 
        {
            return new ShallowEtagHeaderFilter();
        }
    }
}

SimpleRepository.java

@Repository
@RepositoryRestResource(collectionResourceRel = "simples", path = "simples")
public interface SimpleRepository  extends JpaRepository<Simple, Long>
{
}

Simple.java

@Data
@NoArgsConstructor
@Entity
@Table(name = "SIMPLE")
public class Simple
{
    @JsonCreator
    public Simple(@JsonProperty("changeable") String changeable)
    {
        this.changeable = changeable;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID")
    @SequenceGenerator(name = "ID", sequenceName = "ID", allocationSize = 1)
    @Column(name = "ID")
    private Long id;
    
    @Version
    @Column(name = "VERSION")
    private int version;
    
    @Column(name = "CHANGEABLE")
    private String changeable;
}

It works perfectly with just these three classes, I can interact with the exposed JPA repository via postman, the version number is shipped in the http header as an ETag.

Now I want to extend it for a parent-child-relationship where the version is only incremented in the parent entity.

Parent.java

@Data
@NoArgsConstructor
@Entity
@Table(name = "PARENT")
public class Parent
{
    @JsonCreator
    public Parent(@JsonProperty("changeable") String changeable)
    {
        this.changeable = changeable;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PARENT_ID")
    @SequenceGenerator(name = "PARENT_ID", sequenceName = "PARENT_ID", allocationSize = 1)
    @Column(name = "PARENT_ID")
    private Long id;
    
    @Version
    @Column(name = "VERSION")
    private int version;
    
    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Collection<Child> children = new LinkedHashSet<>();
    
    @Column(name = "CHANGEABLE")
    private String changeable;
}

Child.java

@Data
@NoArgsConstructor
@Entity
@Table(name = "CHILD")
public class Child
{
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CHILD_ID")
    @SequenceGenerator(name = "CHILD_ID", sequenceName = "CHILD_ID", allocationSize = 1)
    @Column(name = "CHILD_ID")
    private Long id;
    
//  NO VERSION! Parent version should be incremented on change  
//  @Version
//  @Column(name = "VERSION")
//  private int version;
    
    @ManyToOne(optional = false)
    @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID")
    private Parent parent;
    
    @Column(name = "CHANGEABLE")
    private String changeable;
}

You can find the full example on http://github.com/Meini777/example

What is the best way to implement it? I could code a @RestController on my own instead of using the implicit one from @RepositoryRestResource, but in this case i have implement all the behavior including HATEOAS and ALPS.


Get this bounty!!!

#StackBounty: #java #spring #spring-boot #mocking #integration-testing Spring Boot Integration Testing – Mocking @Service before Applic…

Bounty: 50

I have to create a integration test for a microservice X which downloads, processes and importing csv files from external sftp servers. The whole process is started by a spring boot scheduler task which starts a spring batch job for processing and importing the data. The import process is done by the spring batch writer, which is a restTemplate Repository (so it calls post requests to another microservice Y).

I already managed to mock the sftp server, putting a test file on it and the current integration test is downloading the file. (https://github.com/stefanbirkner/fake-sftp-server-rule/)

My problem is, that the task will be scheduled immediately when the application context starts so there is no trigger like a api call. To get the whole integration test working i have to mock the part where the external microservice Y is called through a restTemplate call. This repository is called in the spring batch writer and this repository is created by a repositoryFactory which is a @Service. The repositoryFactory is injected in the spring batch configuration class.

I already tried to use the @MockBean annotation in the test class as well as in a separate test configuration where i am mocking the create() function of the factory to deliver a repository mock. But at some point it does not work and it delivers still the original object which leads to interupt the import job.

I also tried to use the WireMock library, but also in this case it does not catched any api calls and at some point leads to interrupt the sftp socket. (?)

I hope someone could help me out.

The current test:

@NoArgsConstructor
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = {JsonHalConfig.class})
@TestPropertySource(locations = "classpath:application-test.properties")
@TestMethodOrder(MethodOrderer.MethodName.class)
public class ImportIT {

    @ClassRule
    public static final FakeSftpServerRule sftpServer = new FakeSftpServerRule();
    private static final String PASSWORD = "password";
    private static final String USER = "username";
    private static final int PORT = 14022;

    @BeforeClass
    public static void beforeClass() throws IOException {
        URL resource = getTestResource();
        if (resource != null) {
            sftpServer.setPort(PORT).addUser(USER, PASSWORD);
            sftpServer.createDirectories("/home/username/it-space/IMPORT", "/home/username/it-space/EXPORT");
            sftpServer.putFile("/home/username/it-space/IMPORT/INBOX/testFile.csv",
                    resource.openStream());
        } else {
            throw new IOException("Failed to get test resources");
        }
    }

    private static URL getTestResource() {
        return ImportIT.class.getClassLoader().getResource("testFile.csv");
    }

    @Test
    public void test_A_() throws IOException, RepositoryException {
        assertTrue(true);
    }
}

I tried following configuration classes

(included in @ContextConfiguration)

@Configuration/@TestConfiguration
public class RepositoryTestConfig {
    @Bean
    @Primary
    public IRepositoryFactory repositoryFactory() {
        IRepositoryFactory repositoryFactory = mock(IRepositoryFactory.class);
        IRepository repository = mock(IRepository.class);
        when(repositoryFactory.create(anyString())).thenReturn(repository);
        return repositoryFactory;
    }
}

(as static class in the test class)

    @TestConfiguration/@Configuration
    public static class RepositoryTestConfig {
        @MockBean
        private IRepositoryFactory repositoryFactory;

        @PostConstruct
        public void initMock(){
            IRepository repository = mock(IRepository.class);
            Mockito.when(repositoryFactory.create(anyString())).thenReturn(
                    repository
            );
        }
    }

UPDATE 27.08.2021
I have a RestConfig @Component where a new RestTemplateBuilder is created. I tried to @MockBean this component to deliver a RestTemplateBuilder Mock and injected a MockRestServiceServer object to catch outgoing api calls. But unfortunately it does not work as aspected. Am i missing something? I also tried to create a "TestRestController" to trigger the scheduling of the task but it never delivers the mock…


Get this bounty!!!

#StackBounty: #java #spring #spring-boot #spring-security #spring-security-oauth2 Lazy initialise spring security at runtime + reload s…

Bounty: 50

Spring usually eagerly loading the spring security configuration while starting the application. I’m using OAuth with Spring Security

I’m maintaining a configuration table for storing the SSO related values (like jwk-url, client_id, client_secret). This values will be populated by an admin user via CRUD in the same spring boot application.

Then only the jwk-url is available to be configure in the Spring security configuration (refer below code - jwkSetUri(...)). This would not available at the application startup.

So I wanted to initialise the spring security configuration after the value is loaded into the table, like a lazy loading (@Lazy) at runtime. I know how to do Lazy loading of a regular class/service.

  1. But still I’m not sure how to invoke the configure(HttpSecurity http) method at runtime and how to p
    ass the HttpSecurity parameter. When I just try invoke new ResourceServerConfiguration() like a lazy loading at runtime, I don’t see the configure() method is called. (Or) this class needs to be maintained as bean and lazy load whenever needed. But still not sure about how to call configure() in code.
  2. Another thing is how to refresh/reload the spring security configuration at runtime, if the JWK url is changed by admin. Then only the spring security configuration can take effect of the changes.
@Configuration
@EnableWebSecurity
public class ResourceServerConfiguration extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.cors()
                .and()
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer()
                .authenticationEntryPoint(oAuth2AuthenticationEntryPoint)
                .accessDeniedHandler(oAuth2AccessDeniedHandler)
                .jwt()
                 // Some Auth server URL which would be fetch from table
                .jwkSetUri(ssoConfigService.getActiveSSOCertificateURL()); 
                 // Eg. http://localhost:8090/auth/realms/demo-app/protocol/openid-connect/certs
    }
}

I have already referred these links. But it doesn’t help for my purpose. Any help would be appreciated.

How do I lazy load Spring Security?

How to reload the Configure method of WebSecurityConfigurerAdapter when the application is up and running

Modify Spring Security Config at Runtime

Configure Spring HTTP Security at Runtime


Get this bounty!!!

#StackBounty: #java #spring-boot #out-of-memory #heap-dump #java-heap Java Heap Dump : How to find the objects/class that is taking mem…

Bounty: 50

I found that one of my spring boot project’s memory (RAM consumption) is increasing day by day. When I uploaded the jar file to the AWS server, it was taking 582 MB of RAM (Max Allocated RAM is 1500 MB), but each day, the RAM is increasing by 50MB to 100 MB and today after 5 days, it’s taking 835 MB. Right now the project is having 100-150 users and with normal usage of Rest APIs.

Because of this increase in the RAM, couple of times the application went down with the following error (error found from the logs):

Exception in thread "http-nio-3384-ClientPoller" java.lang.OutOfMemoryError: Java heap space

So to resolve this, I found that by using JAVA Heap Dump, I can find the objects/classes that are taking the memory. So by using Jmap in the command line, I’ve created a heap dump and uploaded it to Heap Hero and Eclipse Memory Analyzer Tool. In both of them I found the following:

1. Total Waste memory is: 64.69MB (73%) (check below screenshot)

enter image description here

2. Out of these, 34.06MB is taken by Byte [] array and LinkedHashmap[] (check below screenshot), which I have never used in my whole project. I searched for it in my project but didn’t found.

enter image description here
3. Following 2 large objects taking 32 MB and 20 MB respectively.

1. Java Static io.netty.buffer.ByteBufUtil.DEFAULT_ALLOCATOR

2. Java Static com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.connectionFinalizerPhantomRefs` 

enter image description here

So I tried to find this netty.buffer. in my project, but I don’t find anything which matched with netty or buffer.

Now my question is how can I reduce this memory leak or how can I find the exact memory consumption objects/class/variable so that I can reduce the heap size.

I know few of the experts will ask for the source code or anything similar to that but I believe that from the heap dump we can find the memory leak or live objects that are available in the memory. I am looking for that option or anything that reduces this heap dump!

I am working on this issue for the past 3 weeks. Any help would be appreciated.
Thank you!


Get this bounty!!!

#StackBounty: #reactjs #spring-boot #deployment #jboss #war How to create a react project war and deploy it on jboss?

Bounty: 50

I know there are many articles on google about this but in some cases they are keeping react(frontend) + springboot(backend) together in a single war, but my requirement is different I want to keep the both wars as separate.

So what I tried till now,

  1. Directly adding the react build folder in jboss->standalone->deployment but it does not work, it works on tomcat but not on jboss
  2. Then I created a new dynamic web maven project and renamed react build folder and added it to maven project webapps directory and created a war, but after deployment its giving 403 error, and I am not getting why.

Here is a snapshot of my folder structure, pom file and error on browser

enter image description here

enter image description here

enter image description here

enter image description here

Please help regarding this have been stuck at it for days now with jboss

Is there any other way to do it, I will be happy to change my approach.

tried this also, did not worked
https://www.megadix.it/blog/create-react-app-servlet/


Get this bounty!!!

#StackBounty: #spring #spring-boot #spring-data-jpa Override entityManager factories mapping at conditionally at runtime

Bounty: 50

I have a multi tenant/DB application implemented using an AbstractRoutingDataSource. Some of the DBs have a slightly different schema and missing some columns in some tables (this is static and known for each DB). Instead of duplicating all repositories and entities for each DB schema I would like to just mark missing columns as transient if the DB does not have the columns (but still save all information if the columns are available).

I was able to override the annotation based mappings in the entity manager factory using an XML based mapping file which I could create for all possible schemas. My idea is to create an entity manager factory for each tenant with the appropriate XML mapping override. Ideally on the first request of a tenant it will instantiate the entity manager factory and then check what mappings override to apply. Pseudo code:

@Configuration
@EnableTransactionManagement
class JPAconfig {

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource myAbstractRoutingDataSource, TenantService tenantService) {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(myAbstractRoutingDataSource);
    em.setPackagesToScan("myPackagesToScan");
    final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaProperties(additionalProperties());
    String schemaVer = env.getProperty("db.schema.version");

    // At runtime based on the tenant, override annotation based mappings
    em.setMappingResources(tenantService.getMappingsForTenant());
    
    return em;
  }
}

Unfortunately LocalContainerEntityManagerFactoryBean is a factory bean and only seems to allow singleton or prototype scope. It would also be okay to define all possible LocalContainerEntityManagerFactoryBean beans at compile time and somehow select the correct factory based on the tenant at runtime.


Get this bounty!!!

#StackBounty: #spring-boot #spring-mvc How to get the DispatcherServlet from spring WebApplicationContext?

Bounty: 100

How to get the DispatcherServlet instance from a spring WebApplicationContext object?

I want to perform a direct request to the the front controller servlet (avoiding the network interface) and check the response from a spring application, e.g. WebApplicationContext instance.

Notice, we are not able to use MockMvc to check the HTML rendered by JSP because: "if you use JSPs, you can verify the JSP page to which the request was forwarded, but no HTML is rendered"(according to MockMvc vs End-to-End Tests)

So maybe if we get the DispatcherServlet instance we could perform the request through its doDispatch method and check the content from response.


Get this bounty!!!

#StackBounty: #java #spring #spring-boot #spring-mvc #spring-test Spring Boot test Filter

Bounty: 50

I’ve been trying a couple different approaches to testing a Filter however I’m continuously getting one error or another so I’m hoping for some direction.

Here’s a dummy Filter that should just do a redirect.


package org.example.filters;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class RedirectFilter implements Filter {
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) req;
    chain.sendRedirect("/splash");
  }
}

And a basic Spring Boot Application class:

package org.example;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApplicationClass {

}

I think I’m just not clear on what ‘level’ of Spring Boot Test I’m trying to do, here’s some attempts I’ve done and the errors:

Option 1. Trying with mocks, for example from here

package org.example.filters;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

public class LocaleFilterIntegrationTestStandalone {

  @Test
  public void whenNoLocaleRedirectToSplash() throws Exception {
    standaloneSetup(new TestController()).addFilters(new RedirectFilter()).build().perform(get("/"))
        .andExpect(status().isFound()).andExpect(redirectedUrl("/splash"));
  }

  @Controller
  private static class TestController {
    @GetMapping("/")
    public String get() {
      return "got it";
    }
  }
}

Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse

Option 2, try using @WebMvcTest, which has the same issue as Option 1

package org.example.filters;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.bind.annotation.GetMapping;

@WebMvcTest
public class LocaleFilterIntegrationTestWebMvc {
  @Autowired
  private MockMvc mvc;

  @Test
  public void noLanguageShouldRedirectToSplash() throws Exception {
    mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("/splash"));
  }

  @Controller
  private static class TestController {
    @GetMapping("/")
    public String get() {
      return "got it";
    }
  }
}

Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse

Option 3, try booting the whole context, which I think is required to be able to cast to HttpServletRequest:

package org.example.filters;

import java.net.URI;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class LocaleFilterIntegrationTest {
  @LocalServerPort
  private int port;

  @Autowired
  private TestRestTemplate restTemplate;

  @Test
  public void noLanguageShouldRedirectToSplash() throws Exception {
    URI uri = new URI("http", "localhost:" + port, "/", null, null);
    String result = restTemplate.getForObject(uri.toString(), String.class);
    // not sure how, but test for redirect...
  }

  @Controller
  private static class TestController {
    @GetMapping("/")
    public String get() {
      return "got it";
    }
  }
}

Error: class org.apache.catalina.connector.RequestFacade cannot be cast to class javax.servlet.http.HttpServletResponse

Option 4, suggested by @m-deinem

package org.example.filters;

import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class LocaleFilterIntegrationTestPlain {
  private final RedirectFilter redirectFilter = new RedirectFilter();

  @Test
  public void noLanguageShouldRedirectToSplash() throws Exception {
    MockHttpServletRequest req = new MockHttpServletRequest();
    MockHttpServletResponse res = new MockHttpServletResponse();
    MockFilterChain chain = new MockFilterChain();
    redirectFilter.doFilter(req, res, chain);
  }
}

Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse


Get this bounty!!!